summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-04-09 16:11:26 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-04-09 16:17:31 +0100
commitdba43d370b984e262f6fe5920b38b433f4bd392b (patch)
tree856dacaab521c878b8daa883b486a1c0642fbfb2 /src
parentf14d6cbff3b9766f5fa834282a4eca6636b6fd7d (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.c53
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);
}