From dba43d370b984e262f6fe5920b38b433f4bd392b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 Apr 2014 16:11:26 +0100 Subject: [PATCH] sna: Use pwrite to update physical cursors Older hardware uses physical addresses for its cursor, which are implemented by the kernel in an incoherent fashion. Maybe with stolen support this would be different... Fixes regression on [845g, 945g] from commit 25ca8f136cef9e1bdf06967bf8e78c87b54ffce2 Author: Chris Wilson Date: Thu Mar 27 14:15:30 2014 +0000 sna: Support variable sized cursors Reported-by: Knut Petersen Signed-off-by: Chris Wilson --- src/sna/sna_display.c | 53 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 664d42c7..a9558d22 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -3093,12 +3093,18 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna) 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; - } + /* Old hardware uses physical addresses, which the kernel + * implements in an incoherent fashion requiring a pwrite. + */ + if (sna->kgem.gen >= 033) { + 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; + } + } else + c->image = NULL; __DBG(("%s: handle=%d, allocated %d\n", __FUNCTION__, c->handle, size)); @@ -3114,7 +3120,7 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna) static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) { struct sna_cursor *cursor; - uint32_t *src; + uint32_t *src, *image; int width, height, size, x, y; Rotation rotation; @@ -3198,10 +3204,21 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) } } + image = cursor->image; + if (image == NULL) { + image = malloc(4*size*size); + if (image == NULL) { + if (src != (uint32_t *)sna->cursor.ref->bits->argb) + free(src); + return NULL; + } + + cursor->last_width = cursor->last_height = size; + } if (width < cursor->last_width || height < cursor->last_height) - memset(cursor->image, 0, 4*size*size); + memset(image, 0, 4*size*size); if (rotation == RR_Rotate_0) { - memcpy_blt(src, cursor->image, 32, + memcpy_blt(src, image, 32, width * 4, size * 4, 0, 0, 0, 0, @@ -3217,10 +3234,23 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) pixel = src[yin * width + xin]; else pixel = 0; - cursor->image[y * size + x] = pixel; + image[y * size + x] = pixel; } } + if (image != cursor->image) { + struct drm_i915_gem_pwrite pwrite; + + VG_CLEAR(pwrite); + pwrite.handle = cursor->handle; + pwrite.offset = 0; + pwrite.size = 4*size*size; + pwrite.data_ptr = (uintptr_t)image; + (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); + + free(image); + } + if (src != (uint32_t *)sna->cursor.ref->bits->argb) free(src); @@ -3365,7 +3395,8 @@ sna_hide_cursors(ScrnInfoPtr scrn) while (sna->cursor.cursors) { struct sna_cursor *cursor = sna->cursor.cursors; sna->cursor.cursors = cursor->next; - munmap(cursor->image, cursor->alloc); + if (cursor->image) + munmap(cursor->image, cursor->alloc); gem_close(sna->kgem.fd, cursor->handle); free(cursor); }