Commit 7f8127d2 authored by Peter Hutterer's avatar Peter Hutterer

dix: if we run out of space for new touch events, resize the queue

The SIGIO handler forces us to drop the current touch and schedule the
actual resize for later. Should not happen if the device sets up the
TouchClassRec with the correct number of touchpoints.
Co-authored-by: default avatarDaniel Stone <daniel@fooishbar.org>
Signed-off-by: default avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: default avatarChase Douglas <chase.douglas@canonical.com>
parent 758bc57b
......@@ -34,6 +34,9 @@
#include "eventstr.h"
#include "exevents.h"
/* If a touch queue resize is needed, the device id's bit is set. */
static unsigned char resize_waiting[(MAXDEVICES + 7)/8];
/**
* Some documentation about touch points:
* The driver submits touch events with it's own (unique) touch point ID.
......@@ -53,6 +56,60 @@
* contains amongst other things the sprite trace and delivery information.
*/
/**
* Check which devices need a bigger touch event queue and grow their
* last.touches by half it's current size.
*
* @param client Always the serverClient
* @param closure Always NULL
*
* @return Always True. If we fail to grow we probably will topple over soon
* anyway and re-executing this won't help.
*/
static Bool
TouchResizeQueue(ClientPtr client, pointer closure)
{
int i;
OsBlockSignals();
/* first two ids are reserved */
for (i = 2; i < MAXDEVICES; i++)
{
DeviceIntPtr dev;
DDXTouchPointInfoPtr tmp;
size_t size;
if (!BitIsOn(resize_waiting, i))
continue;
ClearBit(resize_waiting, i);
/* device may have disappeared by now */
dixLookupDevice(&dev, i, serverClient, DixWriteAccess);
if (!dev)
continue;
/* Need to grow the queue means dropping events. Grow sufficiently so we
* don't need to do it often */
size = dev->last.num_touches + dev->last.num_touches/2 + 1;
tmp = realloc(dev->last.touches, size * sizeof(*dev->last.touches));
if (tmp)
{
int i;
dev->last.touches = tmp;
for (i = dev->last.num_touches; i < size; i++)
TouchInitDDXTouchPoint(dev, &dev->last.touches[i]);
dev->last.num_touches = size;
}
}
OsReleaseSignals();
return TRUE;
}
/**
* Given the DDX-facing ID (which is _not_ DeviceEvent::detail.touch), find the
* associated DDXTouchPointInfoRec.
......@@ -133,7 +190,16 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
return ti;
}
/* If we get here, then we've run out of touches, drop the event */
/* If we get here, then we've run out of touches and we need to drop the
* event (we're inside the SIGIO handler here) schedule a WorkProc to
* grow the queue for us for next time. */
ErrorF("%s: not enough space for touch events (max %d touchpoints). "
"Dropping this event.\n", dev->name, dev->last.num_touches);
if (!BitIsOn(resize_waiting, dev->id)) {
SetBit(resize_waiting, dev->id);
QueueWorkProc(TouchResizeQueue, serverClient, NULL);
}
return NULL;
}
......
......@@ -29,6 +29,56 @@
#include "inputstr.h"
#include "assert.h"
static void touch_grow_queue(void)
{
DeviceIntRec dev;
ValuatorClassRec val;
TouchClassRec touch;
size_t size, new_size;
int i;
memset(&dev, 0, sizeof(dev));
dev.id = 2;
dev.valuator = &val;
val.numAxes = 5;
dev.touch = &touch;
inputInfo.devices = &dev;
size = 5;
dev.last.num_touches = size;
dev.last.touches = calloc(dev.last.num_touches, sizeof(*dev.last.touches));
assert(dev.last.touches);
for (i = 0; i < size; i++) {
dev.last.touches[i].active = TRUE;
dev.last.touches[i].ddx_id = i;
dev.last.touches[i].client_id = i * 2;
}
/* no more space, should've scheduled a workproc */
assert(TouchBeginDDXTouch(&dev, 1234) == NULL);
ProcessWorkQueue();
new_size = size + size/2 + 1;
assert(dev.last.num_touches == new_size);
/* make sure we haven't touched those */
for (i = 0; i < size; i++) {
DDXTouchPointInfoPtr t = &dev.last.touches[i];
assert(t->active == TRUE);
assert(t->ddx_id == i);
assert(t->client_id == i * 2);
}
/* make sure those are zero-initialized */
for (i = size; i < new_size; i++) {
DDXTouchPointInfoPtr t = &dev.last.touches[i];
assert(t->active == FALSE);
assert(t->client_id == 0);
assert(t->ddx_id == 0);
}
}
static void touch_find_ddxid(void)
{
DeviceIntRec dev;
......@@ -142,6 +192,7 @@ static void touch_begin_ddxtouch(void)
int main(int argc, char** argv)
{
touch_grow_queue();
touch_find_ddxid();
touch_begin_ddxtouch();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment