From: Tiago V. <vig...@c3...> - 2009-01-05 21:20:58
|
Hi guys, Under KMS, we can build a feature to update the cursor directly to screen without the continuous intervention of the userspace application (X server, wayland, etc). It's a fastpath for DRM based cursors obtained by short-circuit the kernel input layer and DRM module. This would solve all cursor's latency issues that we have in our current model [0]. This series of patches implement such feature using Xorg as the application. Through an ioctl, Xorg tells which devices are responsible for cursors' updates and the kernel evdev driver will spit the events to DRM. DRM will take care about the event informations and also screen limits, and then will draw the cursor on screen. Very intuitive. Right now a thing that is annoying me is how others cursors, sw rendered, could be implemented. I want to avoid two differents sets of the same code in different contexts. IMHO conceptually all these cursor update things must be in-kernel. Painting a cursor image seems to be quite hard as we have to save/restore areas under the cursor. I remember that anholt had an idea concerning this, but I do not remember details. Well, the patches are far from ready to go upstream, but it deploys a system working on this way. So, for now, this mail has two goals: - to people comment on and see in what kind of world we can move. - get a feedback how we can proceed in the case of sw cursors. Please, comment on. Thank you, [0] http://vignatti.wordpress.com/2008/07/29/improving-input-latency/ -- Tiago Vignatti C3SL - Centro de Computação Científica e Software Livre www.c3sl.ufpr.br |
From: Tiago V. <vig...@c3...> - 2009-01-05 21:15:57
|
Signed-off-by: Tiago Vignatti <vig...@c3...> --- drivers/input/evdev.c | 11 +++++++++++ include/linux/drm_cursor.h | 3 +++ 2 files changed, 14 insertions(+), 0 deletions(-) create mode 100644 include/linux/drm_cursor.h diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 3524bef..2b7742e 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -21,6 +21,11 @@ #include <linux/device.h> #include <linux/compat.h> +#define DRM_CURSOR +#ifdef DRM_CURSOR +#include <linux/drm_cursor.h> +#endif + struct evdev { int exist; int open; @@ -77,6 +82,12 @@ static void evdev_event(struct input_handle *handle, event.code = code; event.value = value; +#ifdef DRM_CURSOR + /* TODO: we can do this shortcut better using a callback scheme thus + * drm won't be a dependency for the evdev module */ + drm_collect_input_event(evdev->name, &event); +#endif + rcu_read_lock(); client = rcu_dereference(evdev->grab); diff --git a/include/linux/drm_cursor.h b/include/linux/drm_cursor.h new file mode 100644 index 0000000..aa983d9 --- /dev/null +++ b/include/linux/drm_cursor.h @@ -0,0 +1,3 @@ +#include <linux/input.h> + +void drm_collect_input_event(const char *name, struct input_event *ev); -- 1.5.6.3 -- Tiago Vignatti C3SL - Centro de Computação Científica e Software Livre www.c3sl.ufpr.br |
From: Tiago V. <vig...@c3...> - 2009-01-05 21:11:04
|
Signed-off-by: Tiago Vignatti <vig...@c3...> --- src/i830_dri.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/src/i830_dri.c b/src/i830_dri.c index 07ae646..e9484bd 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -108,6 +108,8 @@ typedef struct drm_i915_flip { #include "dristruct.h" +#include "dricursor.h" + static Bool I830InitVisualConfigs(ScreenPtr pScreen); static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual, drm_context_t hwContext, void *pVisualConfigPriv, @@ -674,6 +676,8 @@ I830DRIScreenInit(ScreenPtr pScreen) return FALSE; } + DRICursorSaveFD(pI830->drmSubFD); + /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */ if (pDRIInfo->frameBufferSize != 0) { int tmp; -- 1.5.6.3 -- Tiago Vignatti C3SL - Centro de Computação Científica e Software Livre www.c3sl.ufpr.br |
From: Jesse B. <jb...@vi...> - 2009-01-16 20:17:56
|
On Monday, January 5, 2009 1:00 pm Tiago Vignatti wrote: > Signed-off-by: Tiago Vignatti <vig...@c3...> > --- > drivers/input/evdev.c | 11 +++++++++++ > include/linux/drm_cursor.h | 3 +++ > 2 files changed, 14 insertions(+), 0 deletions(-) > create mode 100644 include/linux/drm_cursor.h > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c > index 3524bef..2b7742e 100644 > --- a/drivers/input/evdev.c > +++ b/drivers/input/evdev.c > @@ -21,6 +21,11 @@ > #include <linux/device.h> > #include <linux/compat.h> > > +#define DRM_CURSOR > +#ifdef DRM_CURSOR > +#include <linux/drm_cursor.h> > +#endif > + > struct evdev { > int exist; > int open; > @@ -77,6 +82,12 @@ static void evdev_event(struct input_handle *handle, > event.code = code; > event.value = value; > > +#ifdef DRM_CURSOR > + /* TODO: we can do this shortcut better using a callback scheme thus > + * drm won't be a dependency for the evdev module */ > + drm_collect_input_event(evdev->name, &event); > +#endif Yeah there should be some sort of input notifier we can use instead (though afaik most existing stuff goes the other way, e.g. ACPI events calling into the input layer so that fake input events are created). -- Jesse Barnes, Intel Open Source Technology Center |
From: Tiago V. <vig...@c3...> - 2009-01-05 21:16:01
|
This commit adds support for the DRM in-kernel cursor mode setting APIs. When drm_mode_setcrtc is called we also initialize the cursor routines. Through drmCursorSetDev, the userspace app (e.g. Xorg, wayland) tells which devices are responsible for cursors' updates and the kernel input layer will spit the events to DRM (drm_collect_input_event). DRM will take care about the event informations and also screen limits, and then will draw the cursor on screen. Signed-off-by: Tiago Vignatti <vig...@c3...> --- libdrm/xf86drm.c | 20 ++++ libdrm/xf86drm.h | 4 + libdrm/xf86drmMode.c | 4 +- linux-core/Makefile.kernel | 4 +- linux-core/drm_crtc.c | 3 + linux-core/drm_crtc.h | 4 + linux-core/drm_cursor.c | 214 ++++++++++++++++++++++++++++++++++++++++++++ linux-core/drm_cursorP.h | 1 + linux-core/drm_drv.c | 2 + shared-core/drm.h | 11 +++ 10 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 linux-core/drm_cursor.c create mode 100644 linux-core/drm_cursorP.h diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 7b67813..b8f12b6 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2994,3 +2994,23 @@ int drmDropMaster(int fd) ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); return ret; } + +int drmCursorSetDev(int fd, char *name) +{ + struct drm_mode_cursor_setdev arg; + + strncpy(arg.name, name, strlen(name)); + arg.name[strlen(name)] = '\0'; + + return ioctl(fd, DRM_IOCTL_MODE_CURSORSETDEV, &arg); +} + +int drmCursorHotspot(int fd, int hotx, int hoty) +{ + struct drm_mode_cursor_hotspot arg; + + arg.hotx = hotx; + arg.hoty = hoty; + + return ioctl(fd, DRM_IOCTL_MODE_CURSORHOTSPOT, &arg); +} diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index 35780ac..04b7faa 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -663,6 +663,10 @@ extern void drmCloseOnce(int fd); extern int drmSetMaster(int fd); extern int drmDropMaster(int fd); +/* In-kernel cursor update routines */ +extern int drmCursorSetDev(int fd, char *name); +extern int drmCursorHotspot(int fd, int hotx, int hoty); + #include "xf86mm.h" #endif diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index c3921ee..e3a1c76 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -325,7 +325,9 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) arg.x = x; arg.y = y; - return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); +/* Just to see that we're doing the things correctly :) + * return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); */ + return 1; } /* diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 246c0b3..53f5795 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -7,8 +7,8 @@ # $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel,v 1.18 2003/08/16 17:59:17 dawes Exp $ # -drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ - drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ +drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_cursor.o drm_dma.o \ + drm_drawable.o drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \ drm_memory_debug.o ati_pcigart.o drm_sman.o \ diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 7ee3321..e015342 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -33,6 +33,7 @@ #include "drm.h" #include "drmP.h" #include "drm_crtc.h" +#include "drm_cursorP.h" struct drm_prop_enum_list { int type; @@ -1412,6 +1413,8 @@ int drm_mode_setcrtc(struct drm_device *dev, set.fb =fb; ret = crtc->funcs->set_config(&set); + drm_cursor_init(crtc); + out: kfree(connector_set); mutex_unlock(&dev->mode_config.mutex); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index bfccdeb..15e9aca 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -676,6 +676,10 @@ extern int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_cursor_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_cursor_setdev_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_cursor_hotspot_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern int drm_mode_addfb(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_rmfb(struct drm_device *dev, diff --git a/linux-core/drm_cursor.c b/linux-core/drm_cursor.c new file mode 100644 index 0000000..832e3b1 --- /dev/null +++ b/linux-core/drm_cursor.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2008 Tiago Vignatti <vig...@c3...> + * + * DRM cursor and related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Tiago Vignatti <vig...@c3...> + */ + +#include <linux/drm_cursor.h> +#include "drmP.h" +#include "drm_cursorP.h" + + +#define DEBUG_CURSOR 1 + +/* XXX: define a sane max */ +#define MAX_INPUT_DEVICES 32 + +char *cursor_devices[MAX_INPUT_DEVICES]; +int cursorReady = 0; + +struct drm_cursor { + struct drm_crtc *crtc; + int dx, dy; + int hotx, hoty; +}; +struct drm_cursor *cursor = NULL; + + +int drm_cursor_init(struct drm_crtc *crtc) +{ + int i, ret = 0; + + DRM_DEBUG("\n"); + + cursor = kzalloc(sizeof(struct drm_cursor), GFP_KERNEL); + if (!cursor) + return -ENOMEM; + + for (i = 0; i < MAX_INPUT_DEVICES; i++) + cursor_devices[i] = NULL; + + cursor->crtc = crtc; + cursor->dx = crtc->fb->width / 2; + cursor->dy = crtc->fb->height / 2; + cursor->hotx = 0; + cursor->hoty = 0; + + cursorReady = 1; + + return ret; +} + +int drm_mode_cursor_setdev_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor_setdev *arg = data; + int ret = 0; + int i; + + mutex_lock(&dev->mode_config.mutex); +#ifdef DEBUG_CURSOR + printk("%s: %s\n", arg->name, __FUNCTION__); +#endif + if (!arg->name) { + ret = -EINVAL; + goto out; + } + + for (i = 0; i < MAX_INPUT_DEVICES; i++) { + if (!cursor_devices[i]) { + cursor_devices[i] = kzalloc(sizeof(char) * strlen(arg->name), GFP_KERNEL); + if (!cursor_devices[i]) { + ret = -EINVAL; + goto out; + } + + strncpy(cursor_devices[i], arg->name, strlen(arg->name)); + cursor_devices[i][strlen(arg->name)] = '\0'; + goto out; + } + } +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_cursor_hotspot_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_cursor_hotspot *arg = data; + struct drm_crtc *crtc; + int ret = 0; + + + mutex_lock(&dev->mode_config.mutex); + crtc = cursor->crtc; +#ifdef DEBUG_CURSOR + printk("%s: %d %d\n", __FUNCTION__, arg->hotx, arg->hoty); +#endif + + cursor->hotx = arg->hotx; + cursor->hoty = arg->hoty; + + /* Fake a movement to update the cursor's position */ + if (crtc->funcs->cursor_move) { + ret = crtc->funcs->cursor_move(crtc, cursor->dx - cursor->hotx, + cursor->dy - cursor->hoty); + } else { + DRM_ERROR("crtc does not support cursor shorcut\n"); + ret = -EFAULT; + goto out; + } + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +static void clip_axis(int *val, int max_value) +{ + if (*val < 0) + *val = 0; + if (*val >= max_value) + *val = max_value - 1; +} + +static int drm_is_cursor_dev(const char *name) +{ + int i; + + for (i = 0; i < MAX_INPUT_DEVICES && cursor_devices[i]; i++) { + if (!strcmp(name, cursor_devices[i])) + return 1; + } + return 0; +} + +void drm_collect_input_event(const char *name, struct input_event *ev) +{ + struct drm_crtc *crtc; + char evname[27]; + + + crtc = cursor->crtc; + snprintf(evname, sizeof(evname), "/dev/input/%s", name); + + if (!cursorReady) + return; + if (!drm_is_cursor_dev(evname)) + return; + + switch (ev->type) { + case EV_REL: + switch (ev->code) { + case REL_X: + cursor->dx += ev->value; + break; + + case REL_Y: + cursor->dy += ev->value; + break; + } +/* TODO: convert abs to rel motion */ +#if 0 + case EV_ABS: + switch (ev->code) { + case ABS_X: + cursor->dx = ev->value; + break; + case ABS_Y: + cursor->dy = ev->value; + break; + } +#endif + break; + } + + clip_axis(&cursor->dx, crtc->fb->width); + clip_axis(&cursor->dy, crtc->fb->height); + +#ifdef DEBUG_CURSOR + printk("drm: dx:%d (%d), dy:%d (%d)\n", cursor->dx, + cursor->hotx, + cursor->dy, + cursor->hoty); +#endif + if (crtc->funcs->cursor_move) { + crtc->funcs->cursor_move(crtc, cursor->dx - cursor->hotx, + cursor->dy - cursor->hoty); + } else { + DRM_ERROR("crtc does not support cursor shorcut\n"); + } +} +EXPORT_SYMBOL(drm_collect_input_event); diff --git a/linux-core/drm_cursorP.h b/linux-core/drm_cursorP.h new file mode 100644 index 0000000..3cdc73e --- /dev/null +++ b/linux-core/drm_cursorP.h @@ -0,0 +1 @@ +int drm_cursor_init(struct drm_crtc *crtc); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 4e7c531..55891ee 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -128,6 +128,8 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSORSETDEV, drm_mode_cursor_setdev_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSORHOTSPOT, drm_mode_cursor_hotspot_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), diff --git a/shared-core/drm.h b/shared-core/drm.h index 4119064..d6290d1 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1238,6 +1238,15 @@ struct drm_mode_crtc_lut { uint64_t blue; }; +struct drm_mode_cursor_setdev { + char name[32]; +}; + +struct drm_mode_cursor_hotspot { + int hotx; + int hoty; +}; + /** * \name Ioctls Definitions */ @@ -1356,6 +1365,8 @@ struct drm_mode_crtc_lut { #define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xB0, struct drm_mode_get_encoder) #define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xB1, struct drm_mode_crtc_lut) #define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xB2, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_CURSORSETDEV DRM_IOWR(0xB3, struct drm_mode_cursor_setdev) +#define DRM_IOCTL_MODE_CURSORHOTSPOT DRM_IOWR(0xB4, struct drm_mode_cursor_hotspot) /*@}*/ -- 1.5.6.3 -- Tiago Vignatti C3SL - Centro de Computação Científica e Software Livre www.c3sl.ufpr.br |
From: Jesse B. <jb...@vi...> - 2009-01-16 20:18:17
|
On Monday, January 5, 2009 12:58 pm Tiago Vignatti wrote: > + > +int drmCursorSetDev(int fd, char *name) > +{ > + struct drm_mode_cursor_setdev arg; > + > + strncpy(arg.name, name, strlen(name)); > + arg.name[strlen(name)] = '\0'; arg.name is on 32 bytes wide, right? So shouldn't the lat arg of strncpy be the size of arg.name rather than the passed in value? (I think this applies to the ioctl arg parsing as well.) > +/* XXX: define a sane max */ > +#define MAX_INPUT_DEVICES 32 > + > +char *cursor_devices[MAX_INPUT_DEVICES]; You could probably just make this a list instead, included in the drm mode_config struct perhaps. > +int cursorReady = 0; > + > +struct drm_cursor { > + struct drm_crtc *crtc; > + int dx, dy; > + int hotx, hoty; > +}; > +struct drm_cursor *cursor = NULL; > + > + > +int drm_cursor_init(struct drm_crtc *crtc) > +{ > + int i, ret = 0; > + > + DRM_DEBUG("\n"); > + > + cursor = kzalloc(sizeof(struct drm_cursor), GFP_KERNEL); > + if (!cursor) > + return -ENOMEM; > + > + for (i = 0; i < MAX_INPUT_DEVICES; i++) > + cursor_devices[i] = NULL; > + > + cursor->crtc = crtc; > + cursor->dx = crtc->fb->width / 2; > + cursor->dy = crtc->fb->height / 2; > + cursor->hotx = 0; > + cursor->hoty = 0; > + > + cursorReady = 1; Seems like the cursor should be part of the mode config structure instead? And maybe you could just use mode_config->cursor to see whether one was active instead of having a separate cursorReady flag... > + /* Fake a movement to update the cursor's position */ > + if (crtc->funcs->cursor_move) { > + ret = crtc->funcs->cursor_move(crtc, cursor->dx - cursor->hotx, > + cursor->dy - cursor->hoty); > + } else { > + DRM_ERROR("crtc does not support cursor shorcut\n"); > + ret = -EFAULT; > + goto out; > + } This should probably just be -EINVAL or -ENOTTY to indicate that the low level driver doesn't support this feature. Then you wouldn't need the error message either. > +struct drm_mode_cursor_setdev { > + char name[32]; > +}; > + I wonder if this should be just a dev_t instead... > +struct drm_mode_cursor_hotspot { > + int hotx; > + int hoty; > +}; > + > /** > * \name Ioctls Definitions > */ > @@ -1356,6 +1365,8 @@ struct drm_mode_crtc_lut { > #define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xB0, struct > drm_mode_get_encoder) #define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xB1, > struct drm_mode_crtc_lut) #define DRM_IOCTL_MODE_SETGAMMA > DRM_IOWR(0xB2, struct drm_mode_crtc_lut) +#define > DRM_IOCTL_MODE_CURSORSETDEV DRM_IOWR(0xB3, struct > drm_mode_cursor_setdev) +#define DRM_IOCTL_MODE_CURSORHOTSPOT > DRM_IOWR(0xB4, struct drm_mode_cursor_hotspot) Combined with the other cursor ioctl this may be sufficient to support even sw rendered cursors (if we ever decided to do that), though we'd probably want to add another flag to the existing cursor ioctl to allow for control of accel methods (which would be another thing to add). It would be cool if you could update this patchset against the upstream kernel and post it to lkml; the input guys may have some feedback too. -- Jesse Barnes, Intel Open Source Technology Center |
From: Tiago V. <vig...@c3...> - 2009-01-05 21:16:06
|
This implementation gives two ioctls APIs (DRICursorSetDev, DRICursorHotspot) to interface with the DRM modesetting cursors. For now this patch disables the pointer acceleration scheme. Signed-off-by: Tiago Vignatti <vig...@c3...> --- Makefile.am | 1 + configure.ac | 4 ++- dix/getevents.c | 2 + dricursor/Makefile.am | 9 +++++++ dricursor/dricursor.c | 51 ++++++++++++++++++++++++++++++++++++++++ hw/xfree86/common/xf86Xinput.c | 8 ++++++ hw/xfree86/ramdac/xf86Cursor.c | 3 ++ include/Makefile.am | 1 + include/dricursor.h | 3 ++ 9 files changed, 81 insertions(+), 1 deletions(-) create mode 100644 dricursor/Makefile.am create mode 100644 dricursor/dricursor.c create mode 100644 include/dricursor.h diff --git a/Makefile.am b/Makefile.am index aa9c8b6..c641710 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,6 +19,7 @@ endif SUBDIRS = \ doc \ + dricursor \ include \ dix \ fb \ diff --git a/configure.ac b/configure.ac index 93e3a60..a83da6c 100644 --- a/configure.ac +++ b/configure.ac @@ -842,6 +842,7 @@ AC_SUBST([GLX_DEFINES]) AM_CONDITIONAL(DRI, test "x$DRI" = xyes) if test "x$DRI" = xyes; then + DRICURSOR_LIB='$(top_builddir)/dricursor/libdricursor.la' AC_DEFINE(XF86DRI, 1, [Build DRI extension]) PKG_CHECK_MODULES([DRIPROTO], [xf86driproto]) PKG_CHECK_MODULES([LIBDRM], [libdrm >= 2.3.0]) @@ -1228,7 +1229,7 @@ if test "x$XORG" = xyes; then XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' XORG_INCS="$XORG_DDXINCS $XORG_OSINCS" XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H" - XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $SELINUX_LIB" + XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $SELINUX_LIB $DRICURSOR_LIB" PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0]) SAVE_LIBS=$LIBS @@ -1803,6 +1804,7 @@ damageext/Makefile dbe/Makefile dix/Makefile doc/Makefile +dricursor/Makefile fb/Makefile record/Makefile config/Makefile diff --git a/dix/getevents.c b/dix/getevents.c index 4770a69..8d24075 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -880,12 +880,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, } } else { +#if 0 if (flags & POINTER_ACCELERATE && pDev->valuator->accelScheme.AccelSchemeProc){ pDev->valuator->accelScheme.AccelSchemeProc( pDev, first_valuator, num_valuators, valuators, ms); } +#endif if(v0) x += *v0; if(v1) y += *v1; diff --git a/dricursor/Makefile.am b/dricursor/Makefile.am new file mode 100644 index 0000000..017a861 --- /dev/null +++ b/dricursor/Makefile.am @@ -0,0 +1,9 @@ +noinst_LTLIBRARIES = libdricursor.la + +AM_CFLAGS = @DIX_CFLAGS@ @LIBDRM_CFLAGS@ + +INCLUDES = $(XORG_INCS) \ + -I$(top_srcdir)/include + +libdricursor_la_SOURCES = dricursor.c +libdricursor_la_LIBADD = @LIBDRM_LIBS@ diff --git a/dricursor/dricursor.c b/dricursor/dricursor.c new file mode 100644 index 0000000..933baac --- /dev/null +++ b/dricursor/dricursor.c @@ -0,0 +1,51 @@ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <xf86drm.h> +#include "dricursor.h" + + +int drmFD = -1; + +/** + * Save the DRM fd. Called by the DRM user, i.e. the video driver. + * + * @param The drm file-descriptor + */ +void +DRICursorSaveFD(int fd) { + fprintf(stderr, "%s: %d\n", __FUNCTION__, fd); + drmFD = fd; +} + +/** + * drmCursorSetDev ioctl interface. + * + * Notify DRM about which devices are responsible for cursor updates. + * + * @param The device path (e.g. /dev/input/event0) + * @return On success zero is returned. + */ +int +DRICursorSetDev(char *path) +{ + fprintf(stderr, "%s: %d: %s\n", __FUNCTION__, drmFD, path); + return drmCursorSetDev(drmFD, path); +} + +/** + * drmCursorHotspot ioctl interface. + * + * When the application updates the sprite, DRM must be notified by the + * changes. + * + * @param The hotspot of the cursor. + * @return On success zero is returned. + */ +int +DRICursorHotspot(int hotx, int hoty) +{ + return drmCursorHotspot(drmFD, hotx, hoty); +} diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 8eaa118..c4f3f30 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -89,6 +89,7 @@ #endif #include "os.h" +#include "dricursor.h" EventListPtr xf86Events = NULL; @@ -471,6 +472,7 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) DeviceIntPtr dev = NULL; int rval = Success; int is_auto = 0; + char *path; idev = xcalloc(sizeof(*idev), 1); if (!idev) @@ -514,6 +516,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) } } + if (strcasecmp(option->key, "path") == 0) + path = xstrdup(option->value); + /* Right now, the only automatic config we know of is HAL. */ if (strcmp(option->key, "_source") == 0 && strcmp(option->value, "server/hal") == 0) { @@ -582,6 +587,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) (!is_auto || xf86Info.autoEnableDevices)) EnableDevice(dev); + if (IsPointerDevice(dev)) + DRICursorSetDev(path); + /* send enter/leave event, update sprite window */ CheckMotion(NULL, dev); diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c index 592eaad..93bee64 100644 --- a/hw/xfree86/ramdac/xf86Cursor.c +++ b/hw/xfree86/ramdac/xf86Cursor.c @@ -7,6 +7,7 @@ #include "xf86CursorPriv.h" #include "colormapst.h" #include "cursorstr.h" +#include "dricursor.h" /* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for * MPX. @@ -323,6 +324,8 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, ScreenPriv->HotX = pCurs->bits->xhot; ScreenPriv->HotY = pCurs->bits->yhot; + DRICursorHotspot(ScreenPriv->HotX, ScreenPriv->HotY); + if (!infoPtr->pScrn->vtSema) ScreenPriv->SavedCursor = pCurs; diff --git a/include/Makefile.am b/include/Makefile.am index f639048..75123b0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -17,6 +17,7 @@ sdk_HEADERS = \ dixfontstr.h \ dixgrabs.h \ dixstruct.h \ + dricursor.h \ exevents.h \ extension.h \ extinit.h \ diff --git a/include/dricursor.h b/include/dricursor.h new file mode 100644 index 0000000..48ba40e --- /dev/null +++ b/include/dricursor.h @@ -0,0 +1,3 @@ +void DRICursorSaveFD(int); +int DRICursorSetDev(char *); +int DRICursorHotspot(int hotx, int hoty); -- 1.5.6.3 -- Tiago Vignatti C3SL - Centro de Computação Científica e Software Livre www.c3sl.ufpr.br |
From: Peter H. <pet...@wh...> - 2009-01-06 00:04:14
|
On Mon, Jan 05, 2009 at 06:59:18PM -0200, Tiago Vignatti wrote: > This implementation gives two ioctls APIs (DRICursorSetDev, DRICursorHotspot) > to interface with the DRM modesetting cursors. For now this patch disables > the pointer acceleration scheme. > > Signed-off-by: Tiago Vignatti <vig...@c3...> > --- > Makefile.am | 1 + > configure.ac | 4 ++- > dix/getevents.c | 2 + > dricursor/Makefile.am | 9 +++++++ > dricursor/dricursor.c | 51 ++++++++++++++++++++++++++++++++++++++++ > hw/xfree86/common/xf86Xinput.c | 8 ++++++ > hw/xfree86/ramdac/xf86Cursor.c | 3 ++ > include/Makefile.am | 1 + > include/dricursor.h | 3 ++ > 9 files changed, 81 insertions(+), 1 deletions(-) > create mode 100644 dricursor/Makefile.am > create mode 100644 dricursor/dricursor.c > create mode 100644 include/dricursor.h > [...] > diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c > index 8eaa118..c4f3f30 100644 > --- a/hw/xfree86/common/xf86Xinput.c > +++ b/hw/xfree86/common/xf86Xinput.c > @@ -89,6 +89,7 @@ > #endif > > #include "os.h" > +#include "dricursor.h" > > EventListPtr xf86Events = NULL; > > @@ -471,6 +472,7 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) > DeviceIntPtr dev = NULL; > int rval = Success; > int is_auto = 0; > + char *path; > > idev = xcalloc(sizeof(*idev), 1); > if (!idev) > @@ -514,6 +516,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) > } > } > > + if (strcasecmp(option->key, "path") == 0) > + path = xstrdup(option->value); > + > /* Right now, the only automatic config we know of is HAL. */ > if (strcmp(option->key, "_source") == 0 && > strcmp(option->value, "server/hal") == 0) { > @@ -582,6 +587,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) > (!is_auto || xf86Info.autoEnableDevices)) > EnableDevice(dev); > > + if (IsPointerDevice(dev)) > + DRICursorSetDev(path); > + > /* send enter/leave event, update sprite window */ > CheckMotion(NULL, dev); > This hunk is wrong, you need to check for attachment of the device, not just for IsPointerDevice. A device that isn't attached doesn't have a visible cursor. This would also mean that you'd need to put a hook into AttachDevice to reset when the attachment changes. (the two hunks before seem a bit out of place too) Cheers, Peter |
From: Jesse B. <jb...@vi...> - 2009-01-16 20:23:56
|
On Monday, January 5, 2009 12:55 pm Tiago Vignatti wrote: > Right now a thing that is annoying me is how others cursors, sw rendered, > could be implemented. I want to avoid two differents sets of the same code > in different contexts. IMHO conceptually all these cursor update things > must be in-kernel. Painting a cursor image seems to be quite hard as we > have to save/restore areas under the cursor. I remember that anholt had an > idea concerning this, but I do not remember details. I really like the idea of having this in the kernel for latency reasons, but yeah we do need to solve the sw case as well as implementing some acceleration code. OTOH it might be reasonable to push the problem of multiple, large, and or funky format cursors out to userspace, since those are relatively uncommon (64x64 32 bit ARGB ought to be enough for everybody right? :). -- Jesse Barnes, Intel Open Source Technology Center |
From: Rémi C. <re...@ge...> - 2009-01-17 00:17:07
|
Le 16/01/2009 21:21, Jesse Barnes a écrit : > On Monday, January 5, 2009 12:55 pm Tiago Vignatti wrote: >> Right now a thing that is annoying me is how others cursors, sw rendered, >> could be implemented. I want to avoid two differents sets of the same code >> in different contexts. IMHO conceptually all these cursor update things >> must be in-kernel. Painting a cursor image seems to be quite hard as we >> have to save/restore areas under the cursor. I remember that anholt had an >> idea concerning this, but I do not remember details. > > I really like the idea of having this in the kernel for latency reasons, but > yeah we do need to solve the sw case as well as implementing some > acceleration code. OTOH it might be reasonable to push the problem of > multiple, large, and or funky format cursors out to userspace, since those > are relatively uncommon (64x64 32 bit ARGB ought to be enough for everybody > right? :). Not for firefox. Any drag&drop in gecko will result in huge ARGB cursors. Even just dragging and dropping a tab results in a cursor that's at least 150x20px. Cheers Rémi |
From: Jesse B. <jb...@vi...> - 2009-01-19 18:03:06
|
On Friday, January 16, 2009 1:55 pm Rémi Cardona wrote: > Le 16/01/2009 21:21, Jesse Barnes a écrit : > > On Monday, January 5, 2009 12:55 pm Tiago Vignatti wrote: > >> Right now a thing that is annoying me is how others cursors, sw > >> rendered, could be implemented. I want to avoid two differents sets of > >> the same code in different contexts. IMHO conceptually all these cursor > >> update things must be in-kernel. Painting a cursor image seems to be > >> quite hard as we have to save/restore areas under the cursor. I remember > >> that anholt had an idea concerning this, but I do not remember details. > > > > I really like the idea of having this in the kernel for latency reasons, > > but yeah we do need to solve the sw case as well as implementing some > > acceleration code. OTOH it might be reasonable to push the problem of > > multiple, large, and or funky format cursors out to userspace, since > > those are relatively uncommon (64x64 32 bit ARGB ought to be enough for > > everybody right? :). > > Not for firefox. Any drag&drop in gecko will result in huge ARGB > cursors. Even just dragging and dropping a tab results in a cursor > that's at least 150x20px. Gah, yeah forgot about drag & drop of big icons... Maybe Kristian was right that all cursors should be done in software; hardware just doesn't provide the flexibility desktops want these days. -- Jesse Barnes, Intel Open Source Technology Center |
From: Michel D. <mi...@da...> - 2009-01-21 10:47:01
|
On Mon, 2009-01-19 at 10:03 -0800, Jesse Barnes wrote: > On Friday, January 16, 2009 1:55 pm Rémi Cardona wrote: > > Le 16/01/2009 21:21, Jesse Barnes a écrit : > > > On Monday, January 5, 2009 12:55 pm Tiago Vignatti wrote: > > >> Right now a thing that is annoying me is how others cursors, sw > > >> rendered, could be implemented. I want to avoid two differents sets of > > >> the same code in different contexts. IMHO conceptually all these cursor > > >> update things must be in-kernel. Painting a cursor image seems to be > > >> quite hard as we have to save/restore areas under the cursor. I remember > > >> that anholt had an idea concerning this, but I do not remember details. > > > > > > I really like the idea of having this in the kernel for latency reasons, > > > but yeah we do need to solve the sw case as well as implementing some > > > acceleration code. OTOH it might be reasonable to push the problem of > > > multiple, large, and or funky format cursors out to userspace, since > > > those are relatively uncommon (64x64 32 bit ARGB ought to be enough for > > > everybody right? :). > > > > Not for firefox. Any drag&drop in gecko will result in huge ARGB > > cursors. Even just dragging and dropping a tab results in a cursor > > that's at least 150x20px. > > Gah, yeah forgot about drag & drop of big icons... Maybe Kristian was right > that all cursors should be done in software; hardware just doesn't provide > the flexibility desktops want these days. Yeah, I suspect allowing the compositing manager to render cursors might be more useful in the long term. Then we 'just' need to make sure the composited cursors don't lag more than one frame behind the input devices. -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Rémi C. <re...@ge...> - 2009-01-19 23:48:32
|
Le 19/01/2009 19:03, Jesse Barnes a écrit : > Gah, yeah forgot about drag& drop of big icons... Maybe Kristian was right > that all cursors should be done in software; hardware just doesn't provide > the flexibility desktops want these days. Maybe there could be a way to prioritize input events over rendering requests within the server, but going full software for the cursor sounds like the best solution. It's only a pixmap after all... Cheers -- Rémi Cardona LRI, INRIA rem...@lr... re...@ge... |
From: Daniel S. <da...@fo...> - 2009-01-21 03:39:26
|
On Tue, Jan 20, 2009 at 12:47:44AM +0100, Rémi Cardona wrote: > Le 19/01/2009 19:03, Jesse Barnes a écrit : > > Gah, yeah forgot about drag& drop of big icons... Maybe Kristian was right > > that all cursors should be done in software; hardware just doesn't provide > > the flexibility desktops want these days. > > Maybe there could be a way to prioritize input events over rendering > requests within the server, but going full software for the cursor > sounds like the best solution. It's only a pixmap after all... Input events are already hugely prioritised, and indeed done in a SIGIO handler. The main place you tend to fall apart is where the X server is paged out, and you have to wait while other parts of it get paged in. Cheers, Daniel |
From: <ola...@gm...> - 2009-01-25 04:22:38
|
Hi, On Mon, Jan 05, 2009 at 06:55:50PM -0200, Tiago Vignatti wrote: > Under KMS, we can build a feature to update the cursor directly to > screen without the continuous intervention of the userspace > application (X server, wayland, etc). It's a fastpath for DRM based > cursors obtained by short-circuit the kernel input layer and DRM > module. This would solve all cursor's latency issues that we have in > our current model [0]. IHMO punting and pushing this into the kernel in totally the wrong approach. Following this method, you will end up running *everything* in kernel space. (Hi, DOS!) Rather, you should try to figure out *why* the update in user space has latencies not present when doing it in kernel space. Is it because all kernel memory is pinned? (Not true on all systems, BTW.) Is it because event delivery between kernel space and user space triggers bad CPU scheduling? Is it because the handling in user space is not properly prioritized? Once you know the real caus(es), you can go about fixing them -- adapting the design of the user space part, and possibly creating now kernel interfaces is necessary. Ultimately, the kernel/user space distinction is just an address space boundary. There is no fundamental reason why that should cause any latencies. -antrik- |
From: Pekka P. <pq...@ik...> - 2009-01-25 10:28:49
|
On Mon, 5 Jan 2009 18:55:50 -0200 Tiago Vignatti <vig...@c3...> wrote: > Hi guys, > > Under KMS, we can build a feature to update the cursor directly to screen > without the continuous intervention of the userspace application (X server, > wayland, etc). It's a fastpath for DRM based cursors obtained by short-circuit > the kernel input layer and DRM module. This would solve all cursor's latency > issues that we have in our current model [0]. Reducing latency is a good idea, but I don't think circumventing user space altogether is so good. Consider a case where user space is stalled due to excessive load, and let's think about usability. Much of usability comes from feedback given to a user. If cursor updates are done completely inside the kernel, the mouse will continue to work without any hiccups under severe load (this is what you are aiming for, right?). The user clicks a button, and nothing happens in the GUI, since user space is stalled. The user clicks again. And again. Then clicks another button. It takes several seconds for the user to realize, that the clicks are not getting processed. What's worse, all the clicks are probably queued now and will be processed later, possibly leading to unexpected results. If cursor updates had to visit user space, the mouse cursor would stall and jump. This is bad behaviour in itself, but it is also an immediate feedback to the user, that the system is not responsive. The user cannot even reach a button to click it, before he sees that something is going on. In a bad situation, I think this is the less evil choice. This analysis is based on how I use GUIs, and how I think my mother uses GUIs as I've watched her, and we are on a very different level of thinking on how computers and GUIs with a mouse work. Sure, modern GUIs have mouse enter/leave animations for widgets, but it takes an experienced user to notice that hey, that button didn't turn blue when I moved my mouse over it, something's wrong. Making the mouse cursor jump is something no-one can ignore, even when they are in a hurry. If you embrace the idea that cursor updates have to visit user space, I believe it will make implementing things like secondary cursors and cursors that exceed hardware capabilities (e.g. very large cursors) easier. You don't have to implement a full 3D engine driver in the kernel to just blit the cursor image on screen (aren't simple blitting engines and overlays disappearing in the modern development of graphics hardware?). -- Pekka Paalanen http://www.iki.fi/pq/ |
From: <ola...@gm...> - 2009-01-30 18:40:24
|
Hi, On Sun, Jan 25, 2009 at 12:28:37PM +0200, Pekka Paalanen wrote: > Consider a case where user space is stalled due to excessive load, and > let's think about usability. Much of usability comes from feedback > given to a user. > > If cursor updates are done completely inside the kernel, the mouse > will continue to work without any hiccups under severe load (this is > what you are aiming for, right?). The user clicks a button, and > nothing happens in the GUI, since user space is stalled. The user > clicks again. And again. Then clicks another button. It takes several > seconds for the user to realize, that the clicks are not getting > processed. What's worse, all the clicks are probably queued now and > will be processed later, possibly leading to unexpected results. > > If cursor updates had to visit user space, the mouse cursor would > stall and jump. This is bad behaviour in itself, but it is also an > immediate feedback to the user, that the system is not responsive. The > user cannot even reach a button to click it, before he sees that > something is going on. In a bad situation, I think this is the less > evil choice. I totally agree that when the GUI is totally stalled, the curser better be stalled as well... But this is actually a rather untypical case. Much more often the cursor just becomes somewhat jerky under load. The GUI becomes sluggish, but still quite usable. The jerky cursor however makes it much harder to work with it -- a smooth cursor indeed improves usability in this case. On top of that, there is an important psychological effect: With a jerky cursor, the system *feels* much slower than it actually is. Users think, "This X stuff is reall crap: OS X/Windows/whatever is so much smoother..." Sad but true. So ideally, the cursor should remain smooth under some load, but stall when the system is really busy... Any suggestions how to achieve that? :-) -antrik- |
From: Jesse B. <jb...@vi...> - 2009-01-30 18:49:30
|
On Sunday, January 25, 2009 2:28 am Pekka Paalanen wrote: > On Mon, 5 Jan 2009 18:55:50 -0200 > > Tiago Vignatti <vig...@c3...> wrote: > > Hi guys, > > > > Under KMS, we can build a feature to update the cursor directly to screen > > without the continuous intervention of the userspace application (X > > server, wayland, etc). It's a fastpath for DRM based cursors obtained by > > short-circuit the kernel input layer and DRM module. This would solve all > > cursor's latency issues that we have in our current model [0]. > > Reducing latency is a good idea, but I don't think circumventing user space > altogether is so good. Consider a case where user space is stalled due to > excessive load, and let's think about usability. Much of usability comes > from feedback given to a user. > > If cursor updates are done completely inside the kernel, the mouse will > continue to work without any hiccups under severe load (this is what you > are aiming for, right?). The user clicks a button, and nothing happens in > the GUI, since user space is stalled. The user clicks again. And again. > Then clicks another button. It takes several seconds for the user to > realize, that the clicks are not getting processed. What's worse, all the > clicks are probably queued now and will be processed later, possibly > leading to unexpected results. > > If cursor updates had to visit user space, the mouse cursor would stall > and jump. This is bad behaviour in itself, but it is also an immediate > feedback to the user, that the system is not responsive. The user cannot > even reach a button to click it, before he sees that something is going on. > In a bad situation, I think this is the less evil choice. SGI did some use case studies on this. The conclusion they drew was that the cursor should *always* be responsive, and so that's what they did back in the old days on IRIX. Unfortunately we don't have access to that data so we don't know the circumstances under which they tested users, or what the tradeoffs were. But personally I think it sucks when the pointer jumps around, no matter what the situation is with the machine. It makes the whole OS seem cheap and crappy. And for a more "typical" user, I still think smooth movement makes sense. We already have other ways of communicating "system/program busy" than cursor movement (greyed out windows for instance), so I don't buy that argument either. -- Jesse Barnes, Intel Open Source Technology Center |