diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-09 16:11:26 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-09 16:17:31 +0100 |
commit | dba43d370b984e262f6fe5920b38b433f4bd392b (patch) | |
tree | 856dacaab521c878b8daa883b486a1c0642fbfb2 /src | |
parent | f14d6cbff3b9766f5fa834282a4eca6636b6fd7d (diff) |
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 <chris@chris-wilson.co.uk>
Date: Thu Mar 27 14:15:30 2014 +0000
sna: Support variable sized cursors
Reported-by: Knut Petersen <Knut_Petersen@t-online.de>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/sna_display.c | 53 |
1 files 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); } |