summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-04-27 07:55:09 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-04-27 08:35:40 +0100
commit11cc397cb1cded40f7ab43c1add3fd00b97c6bdc (patch)
tree9b710341d67605a81989c969dee087f55061efcf
parent9417f13cc4074ea6e5dad88e054337e93b461a4c (diff)
sna: Preallocate cursors
We need to avoid all allocations within the signal handlers, so preallocate the cursor structs. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77975 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna.h2
-rw-r--r--src/sna/sna_display.c69
2 files changed, 59 insertions, 12 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index fc73f7e6..1e23ac1e 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -298,6 +298,8 @@ struct sna {
unsigned max_size;
bool use_gtt;
+ int num_stash;
+ struct sna_cursor *stash;
void *scratch;
} cursor;
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index f3672e77..14446c7a 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3105,17 +3105,14 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna)
__DBG(("%s(size=%d)\n", __FUNCTION__, size));
- c = malloc(sizeof(*c));
- if (c == NULL)
- return NULL;
+ c = sna->cursor.stash;
+ assert(c);
size = size * size * 4;
c->alloc = ALIGN(size, 4096);
c->handle = gem_create(sna->kgem.fd, c->alloc);
- if (c->handle == 0) {
- free(c);
+ if (c->handle == 0)
return NULL;
- }
/* Old hardware uses physical addresses, which the kernel
* implements in an incoherent fashion requiring a pwrite.
@@ -3124,7 +3121,6 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna)
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
@@ -3135,6 +3131,9 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna)
c->serial = 0;
c->last_width = c->last_height = 0; /* all clear */
+ sna->cursor.num_stash--;
+ sna->cursor.stash = c->next;
+
c->next = sna->cursor.cursors;
sna->cursor.cursors = c;
@@ -3410,6 +3409,7 @@ sna_hide_cursors(ScrnInfoPtr scrn)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
struct sna *sna = to_sna(scrn);
+ struct sna_cursor *cursor, **prev;
int sigio, c;
__DBG(("%s\n", __FUNCTION__));
@@ -3438,14 +3438,22 @@ sna_hide_cursors(ScrnInfoPtr scrn)
sna_crtc->cursor = NULL;
}
- while (sna->cursor.cursors) {
- struct sna_cursor *cursor = sna->cursor.cursors;
- sna->cursor.cursors = cursor->next;
+ for (prev = &sna->cursor.cursors; (cursor = *prev) != NULL; ) {
+ if (cursor->serial == sna->cursor.serial) {
+ prev = &cursor->next;
+ continue;
+ }
+
+ *prev = cursor->next;
if (cursor->image)
munmap(cursor->image, cursor->alloc);
gem_close(sna->kgem.fd, cursor->handle);
- free(cursor);
+
+ cursor->next = sna->cursor.stash;
+ sna->cursor.stash = cursor;
+ sna->cursor.num_stash++;
}
+
sigio_unblock(sigio);
}
@@ -3577,6 +3585,23 @@ static int __cursor_size(CursorPtr cursor)
return size;
}
+static bool
+sna_cursor_preallocate(struct sna *sna)
+{
+ while (sna->cursor.num_stash < 0) {
+ struct sna_cursor *cursor = malloc(sizeof(*cursor));
+ if (!cursor)
+ return false;
+
+ cursor->next = sna->cursor.stash;
+ sna->cursor.stash = cursor;
+
+ sna->cursor.num_stash++;
+ }
+
+ return true;
+}
+
static Bool
sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
{
@@ -3598,6 +3623,9 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
if (sna->cursor.size > sna->cursor.max_size)
return FALSE;
+ if (!sna_cursor_preallocate(sna))
+ return FALSE;
+
sna->cursor.ref = cursor;
cursor->refcnt++;
sna->cursor.serial++;
@@ -3646,11 +3674,28 @@ sna_cursor_pre_init(struct sna *sna)
sna->cursor.max_size = 0;
}
+ sna->cursor.num_stash = -sna->mode.kmode->count_crtcs;
+
xf86DrvMsg(sna->scrn->scrnIndex, X_PROBED,
"Using a maximum size of %dx%d for hardware cursors\n",
sna->cursor.max_size, sna->cursor.max_size);
}
+static void
+sna_cursor_close(struct sna *sna)
+{
+ sna->cursor.serial = 0;
+ sna_hide_cursors(sna->scrn);
+
+ while (sna->cursor.stash) {
+ struct sna_cursor *cursor = sna->cursor.stash;
+ sna->cursor.stash = cursor->next;
+ free(cursor);
+ }
+
+ sna->cursor.num_stash = -sna->mode.kmode->count_crtcs;
+}
+
bool
sna_cursors_init(ScreenPtr screen, struct sna *sna)
{
@@ -4243,7 +4288,7 @@ sna_mode_close(struct sna *sna)
if (sna->flags & SNA_IS_HOSTED)
return;
- sna_hide_cursors(sna->scrn);
+ sna_cursor_close(sna);
for (i = 0; i < config->num_crtc; i++) {
struct sna_crtc *crtc;