diff options
author | Keith Packard <keithp@keithp.com> | 2011-10-24 18:12:23 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-10-24 18:12:23 -0700 |
commit | d9d3a01ffca5e2de650d098231e16205781804c5 (patch) | |
tree | 3b5038c6076a9c9bed0c8ac035cb8b46cf572258 | |
parent | 17416e88dcfcc584fe5f87580d5d2b719b3521c3 (diff) | |
parent | fb55f8f790f69f30b0ab18648c337bde9d41f5ff (diff) |
Merge remote-tracking branch 'jeremyhu/master'
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | hw/xnest/Events.c | 2 | ||||
-rw-r--r-- | hw/xnest/Keyboard.c | 25 | ||||
-rw-r--r-- | hw/xquartz/darwin.c | 2 | ||||
-rw-r--r-- | hw/xquartz/xpr/appledri.c | 137 | ||||
-rw-r--r-- | hw/xquartz/xpr/appledristr.h | 298 | ||||
-rw-r--r-- | mi/mieq.c | 188 | ||||
-rw-r--r-- | test/input.c | 84 |
8 files changed, 543 insertions, 199 deletions
diff --git a/configure.ac b/configure.ac index 4bfa82c24..63d59f92d 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,12 @@ XORG_PROG_RAWCPP # easier overrides at build time. XSERVER_CFLAGS='$(CWARNFLAGS)' +dnl Explicitly add -fno-strict-aliasing since this option should disappear +dnl from util-macros CWARNFLAGS +if test "x$GCC" = xyes ; then + XSERVER_CFLAGS="$XSERVER_CFLAGS -fno-strict-aliasing" +fi + dnl Check for dtrace program (needed to build Xserver dtrace probes) dnl Also checks for <sys/sdt.h>, since some Linux distros have an dnl ISDN trace program named dtrace diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c index 2399313c6..619427ded 100644 --- a/hw/xnest/Events.c +++ b/hw/xnest/Events.c @@ -198,8 +198,6 @@ xnestCollectEvents(void) case DestroyNotify: if (xnestParentWindow != (Window) 0 && X.xdestroywindow.window == xnestParentWindow) - CloseWellKnownConnections(); - OsCleanup(1); exit (0); break; diff --git a/hw/xnest/Keyboard.c b/hw/xnest/Keyboard.c index ec629dcaf..5ef376b91 100644 --- a/hw/xnest/Keyboard.c +++ b/hw/xnest/Keyboard.c @@ -114,11 +114,13 @@ xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) int xnestKeyboardProc(DeviceIntPtr pDev, int onoff) { + XModifierKeymap *modifier_keymap; KeySym *keymap; int mapWidth; int min_keycode, max_keycode; KeySymsRec keySyms; - int i; + CARD8 modmap[MAP_LENGTH]; + int i, j; XKeyboardState values; XkbDescPtr xkb; int op, event, error, major, minor; @@ -130,7 +132,7 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff) #ifdef _XSERVER64 { KeySym64 *keymap64; - int i, len; + int len; keymap64 = XGetKeyboardMapping(xnestDisplay, min_keycode, max_keycode - min_keycode + 1, @@ -147,7 +149,17 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff) max_keycode - min_keycode + 1, &mapWidth); #endif - + + memset(modmap, 0, sizeof(modmap)); + modifier_keymap = XGetModifierMapping(xnestDisplay); + for (j = 0; j < 8; j++) + for(i = 0; i < modifier_keymap->max_keypermod; i++) { + CARD8 keycode; + if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i])) + modmap[keycode] |= 1<<j; + } + XFreeModifiermap(modifier_keymap); + keySyms.minKeyCode = min_keycode; keySyms.maxKeyCode = max_keycode; keySyms.mapWidth = mapWidth; @@ -165,7 +177,12 @@ xnestKeyboardProc(DeviceIntPtr pDev, int onoff) XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb); InitKeyboardDeviceStruct(pDev, NULL, - xnestBell, xnestChangeKeyboardControl); + xnestBell, xnestChangeKeyboardControl); + + XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + modmap, serverClient); + XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls); XkbFreeKeyboard(xkb, 0, False); free(keymap); diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c index b483000f8..465a96d12 100644 --- a/hw/xquartz/darwin.c +++ b/hw/xquartz/darwin.c @@ -621,7 +621,7 @@ void OsVendorInit(void) char *lf; char *home = getenv("HOME"); assert(home); - assert(0 < asprintf(&lf, "%s/Library/Logs/X11.%s.log", home, bundle_id_prefix)); + assert(0 < asprintf(&lf, "%s/Library/Logs/%s.X11.log", home, bundle_id_prefix)); LogInit(lf, ".old"); free(lf); diff --git a/hw/xquartz/xpr/appledri.c b/hw/xquartz/xpr/appledri.c index 1304d5a43..6b4a8a383 100644 --- a/hw/xquartz/xpr/appledri.c +++ b/hw/xquartz/xpr/appledri.c @@ -2,7 +2,7 @@ Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. Copyright 2000 VA Linux Systems, Inc. -Copyright (c) 2002, 2009 Apple Computer, Inc. +Copyright (c) 2002, 2009-2011 Apple Inc. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -102,6 +102,9 @@ ProcAppleDRIQueryVersion( if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + swapl(&rep.patchVersion); } WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep); return Success; @@ -133,6 +136,11 @@ ProcAppleDRIQueryDirectRenderingCapable( if (!LocalClient(client)) rep.isCapable = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + WriteToClient(client, sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep); return Success; @@ -157,6 +165,13 @@ ProcAppleDRIAuthConnection( ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic); rep.authenticated = 0; } + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.authenticated); /* Yes, this is a CARD32 ... sigh */ + } + WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep); return Success; } @@ -216,6 +231,14 @@ ProcAppleDRICreateSurface( rep.key_1 = key[1]; rep.uid = sid; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.key_0); + swapl(&rep.key_1); + swapl(&rep.uid); + } + WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep); return Success; } @@ -277,9 +300,8 @@ ProcAppleDRICreatePixmap(ClientPtr client) rep.stringLength = strlen(path) + 1; - /* No need for swapping, because this only runs if LocalClient is true. */ rep.type = X_Reply; - rep.length = sizeof(rep) + rep.stringLength; + rep.length = bytes_to_int32(rep.stringLength); rep.sequenceNumber = client->sequence; rep.width = width; rep.height = height; @@ -290,8 +312,19 @@ ProcAppleDRICreatePixmap(ClientPtr client) if(sizeof(rep) != sz_xAppleDRICreatePixmapReply) ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); - WriteReplyToClient(client, sizeof(rep), &rep); - (void)WriteToClient(client, rep.stringLength, path); + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.stringLength); + swapl(&rep.width); + swapl(&rep.height); + swapl(&rep.pitch); + swapl(&rep.bpp); + swapl(&rep.size); + } + + WriteToClient(client, sizeof(rep), &rep); + WriteToClient(client, rep.stringLength, path); return Success; } @@ -377,21 +410,107 @@ SProcAppleDRIQueryVersion( } static int +SProcAppleDRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + REQUEST(xAppleDRIQueryDirectRenderingCapableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + return ProcAppleDRIQueryDirectRenderingCapable(client); +} + +static int +SProcAppleDRIAuthConnection( + register ClientPtr client +) +{ + REQUEST(xAppleDRIAuthConnectionReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->magic); + return ProcAppleDRIAuthConnection(client); +} + +static int +SProcAppleDRICreateSurface( + register ClientPtr client +) +{ + REQUEST(xAppleDRICreateSurfaceReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + swapl(&stuff->client_id); + return ProcAppleDRICreateSurface(client); +} + +static int +SProcAppleDRIDestroySurface( + register ClientPtr client +) +{ + REQUEST(xAppleDRIDestroySurfaceReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcAppleDRIDestroySurface(client); +} + +static int +SProcAppleDRICreatePixmap( + register ClientPtr client +) +{ + REQUEST(xAppleDRICreatePixmapReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcAppleDRICreatePixmap(client); +} + +static int +SProcAppleDRIDestroyPixmap( + register ClientPtr client +) +{ + REQUEST(xAppleDRIDestroyPixmapReq); + swaps(&stuff->length); + swapl(&stuff->drawable); + return ProcAppleDRIDestroyPixmap(client); +} + +static int SProcAppleDRIDispatch ( register ClientPtr client ) { REQUEST(xReq); - /* It is bound to be non-local when there is byte swapping */ + switch (stuff->data) + { + case X_AppleDRIQueryVersion: + return SProcAppleDRIQueryVersion(client); + case X_AppleDRIQueryDirectRenderingCapable: + return SProcAppleDRIQueryDirectRenderingCapable(client); + } + if (!LocalClient(client)) return DRIErrorBase + AppleDRIClientNotLocal; - /* only local clients are allowed DRI access */ switch (stuff->data) { - case X_AppleDRIQueryVersion: - return SProcAppleDRIQueryVersion(client); + case X_AppleDRIAuthConnection: + return SProcAppleDRIAuthConnection(client); + case X_AppleDRICreateSurface: + return SProcAppleDRICreateSurface(client); + case X_AppleDRIDestroySurface: + return SProcAppleDRIDestroySurface(client); + case X_AppleDRICreatePixmap: + return SProcAppleDRICreatePixmap(client); + case X_AppleDRIDestroyPixmap: + return SProcAppleDRIDestroyPixmap(client); + default: return BadRequest; } diff --git a/hw/xquartz/xpr/appledristr.h b/hw/xquartz/xpr/appledristr.h index c569719b7..b5ffe5b46 100644 --- a/hw/xquartz/xpr/appledristr.h +++ b/hw/xquartz/xpr/appledristr.h @@ -42,209 +42,225 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define APPLEDRINAME "Apple-DRI" -#define APPLE_DRI_MAJOR_VERSION 1 /* current version numbers */ +#define APPLE_DRI_MAJOR_VERSION 1 /* current version numbers */ #define APPLE_DRI_MINOR_VERSION 0 #define APPLE_DRI_PATCH_VERSION 0 -typedef struct _AppleDRIQueryVersion { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIQueryVersion */ - CARD16 length B16; +typedef struct _AppleDRIQueryVersion +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIQueryVersion */ + CARD16 length B16; } xAppleDRIQueryVersionReq; #define sz_xAppleDRIQueryVersionReq 4 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD16 majorVersion B16; /* major version of DRI protocol */ - CARD16 minorVersion B16; /* minor version of DRI protocol */ - CARD32 patchVersion B32; /* patch version of DRI protocol */ - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DRI protocol */ + CARD16 minorVersion B16; /* minor version of DRI protocol */ + CARD32 patchVersion B32; /* patch version of DRI protocol */ + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIQueryVersionReply; #define sz_xAppleDRIQueryVersionReply 32 -typedef struct _AppleDRIQueryDirectRenderingCapable { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ - CARD16 length B16; - CARD32 screen B32; +typedef struct _AppleDRIQueryDirectRenderingCapable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ + CARD16 length B16; + CARD32 screen B32; } xAppleDRIQueryDirectRenderingCapableReq; #define sz_xAppleDRIQueryDirectRenderingCapableReq 8 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - BOOL isCapable; - BOOL pad2; - BOOL pad3; - BOOL pad4; - CARD32 pad5 B32; - CARD32 pad6 B32; - CARD32 pad7 B32; - CARD32 pad8 B32; - CARD32 pad9 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + BOOL isCapable; + BOOL pad2; + BOOL pad3; + BOOL pad4; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; + CARD32 pad9 B32; } xAppleDRIQueryDirectRenderingCapableReply; #define sz_xAppleDRIQueryDirectRenderingCapableReply 32 -typedef struct _AppleDRIAuthConnection { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICloseConnection */ - CARD16 length B16; - CARD32 screen B32; - CARD32 magic B32; +typedef struct _AppleDRIAuthConnection +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICloseConnection */ + CARD16 length B16; + CARD32 screen B32; + CARD32 magic B32; } xAppleDRIAuthConnectionReq; #define sz_xAppleDRIAuthConnectionReq 12 -typedef struct { - BYTE type; - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 authenticated B32; - CARD32 pad2 B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 authenticated B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIAuthConnectionReply; #define zx_xAppleDRIAuthConnectionReply 32 -typedef struct _AppleDRICreateSurface { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRICreateSurface */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; - CARD32 client_id B32; +typedef struct _AppleDRICreateSurface +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRICreateSurface */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; + CARD32 client_id B32; } xAppleDRICreateSurfaceReq; #define sz_xAppleDRICreateSurfaceReq 16 -typedef struct { - BYTE type; /* X_Reply */ - BOOL pad1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 key_0 B32; - CARD32 key_1 B32; - CARD32 uid B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 key_0 B32; + CARD32 key_1 B32; + CARD32 uid B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRICreateSurfaceReply; #define sz_xAppleDRICreateSurfaceReply 32 -typedef struct _AppleDRIDestroySurface { - CARD8 reqType; /* always DRIReqCode */ - CARD8 driReqType; /* always X_DRIDestroySurface */ - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; +typedef struct _AppleDRIDestroySurface +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIDestroySurface */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRIDestroySurfaceReq; #define sz_xAppleDRIDestroySurfaceReq 12 -typedef struct _AppleDRINotify { - BYTE type; /* always eventBase + event type */ - BYTE kind; - CARD16 sequenceNumber B16; - CARD32 time B32; /* time of change */ - CARD32 pad1 B32; - CARD32 arg B32; - CARD32 pad3 B32; - CARD32 pad4 B32; - CARD32 pad5 B32; - CARD32 pad6 B32; +typedef struct _AppleDRINotify +{ + BYTE type; /* always eventBase + event type */ + BYTE kind; + CARD16 sequenceNumber B16; + CARD32 time B32; /* time of change */ + CARD32 pad1 B32; + CARD32 arg B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRINotifyEvent; #define sz_xAppleDRINotifyEvent 32 -typedef struct { - CARD8 reqType; - CARD8 driReqType; - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; - BOOL doubleSwap; - CARD8 pad1, pad2, pad3; +typedef struct +{ + CARD8 reqType; + CARD8 driReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; + BOOL doubleSwap; + CARD8 pad1, pad2, pad3; } xAppleDRICreateSharedBufferReq; #define sz_xAppleDRICreateSharedBufferReq 16 -typedef struct { - BYTE type; - BYTE data1; - CARD16 sequenceNumber B16; - CARD32 length B32; - CARD32 stringLength B32; /* 0 on error */ - CARD32 width B32; - CARD32 height B32; - CARD32 pad1 B32; - CARD32 pad2 B32; - CARD32 pad3 B32; +typedef struct +{ + BYTE type; + BYTE data1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 stringLength B32; /* 0 on error */ + CARD32 width B32; + CARD32 height B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; } xAppleDRICreateSharedBufferReply; #define sz_xAppleDRICreateSharedBufferReply 32 -typedef struct { - CARD8 reqType; - CARD8 driReqType; - CARD16 length B16; - CARD32 screen B32; - CARD32 drawable B32; +typedef struct +{ + CARD8 reqType; + CARD8 driReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRISwapBuffersReq; #define sz_xAppleDRISwapBuffersReq 12 -typedef struct { - CARD8 reqType; /*1*/ - CARD8 driReqType; /*2*/ - CARD16 length B16; /*4*/ - CARD32 screen B32; /*8*/ - CARD32 drawable B32; /*12*/ +typedef struct +{ + CARD8 reqType; /*1 */ + CARD8 driReqType; /*2 */ + CARD16 length B16; /*4 */ + CARD32 screen B32; /*8 */ + CARD32 drawable B32; /*12 */ } xAppleDRICreatePixmapReq; #define sz_xAppleDRICreatePixmapReq 12 -typedef struct { - BYTE type; /*1*/ - BOOL pad1; /*2*/ - CARD16 sequenceNumber B16; /*4*/ - CARD32 length B32; /*8*/ - CARD32 width B32; /*12*/ - CARD32 height B32; /*16*/ - CARD32 pitch B32; /*20*/ - CARD32 bpp B32; /*24*/ - CARD32 size B32; /*28*/ - CARD32 stringLength B32; /*32*/ +typedef struct +{ + BYTE type; /*1 */ + BOOL pad1; /*2 */ + CARD16 sequenceNumber B16; /*4 */ + CARD32 length B32; /*8 */ + CARD32 width B32; /*12 */ + CARD32 height B32; /*16 */ + CARD32 pitch B32; /*20 */ + CARD32 bpp B32; /*24 */ + CARD32 size B32; /*28 */ + CARD32 stringLength B32; /*32 */ } xAppleDRICreatePixmapReply; #define sz_xAppleDRICreatePixmapReply 32 -typedef struct { - CARD8 reqType; /*1*/ - CARD8 driReqType; /*2*/ - CARD16 length B16; /*4*/ - CARD32 drawable B32; /*8*/ +typedef struct +{ + CARD8 reqType; /*1 */ + CARD8 driReqType; /*2 */ + CARD16 length B16; /*4 */ + CARD32 drawable B32; /*8 */ } xAppleDRIDestroyPixmapReq; #define sz_xAppleDRIDestroyPixmapReq 8 #ifdef _APPLEDRI_SERVER_ -void AppleDRISendEvent ( +void AppleDRISendEvent( #if NeedFunctionPrototypes - int /* type */, - unsigned int /* mask */, - int /* which */, - int /* arg */ + int /* type */ , + unsigned int /* mask */ , + int /* which */ , + int /* arg */ #endif -); + ); #endif /* _APPLEDRI_SERVER_ */ #endif /* _APPLEDRISTR_H_ */ @@ -59,7 +59,12 @@ in this Software without prior written authorization from The Open Group. # include <X11/extensions/dpmsconst.h> #endif -#define QUEUE_SIZE 512 +/* Maximum size should be initial size multiplied by a power of 2 */ +#define QUEUE_INITIAL_SIZE 256 +#define QUEUE_RESERVED_SIZE 64 +#define QUEUE_MAXIMUM_SIZE 4096 +#define QUEUE_DROP_BACKTRACE_FREQUENCY 100 +#define QUEUE_DROP_BACKTRACE_MAX 10 #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen @@ -74,7 +79,9 @@ typedef struct _EventQueue { HWEventQueueType head, tail; /* long for SetInputCheck */ CARD32 lastEventTime; /* to avoid time running backwards */ int lastMotion; /* device ID if last event motion? */ - EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + EventRec *events; /* our queue as an array */ + size_t nevents; /* the number of buckets in our queue */ + size_t dropped; /* counter for number of consecutive dropped events */ mieqHandler handlers[128]; /* custom event handler */ } EventQueueRec, *EventQueuePtr; @@ -99,25 +106,87 @@ static inline void wait_for_server_init(void) { } #endif +static size_t +mieqNumEnqueued(EventQueuePtr eventQueue) { + size_t n_enqueued = 0; + if (eventQueue->nevents) { + /* % is not well-defined with negative numbers... sigh */ + n_enqueued = eventQueue->tail - eventQueue->head + eventQueue->nevents; + if (n_enqueued >= eventQueue->nevents) + n_enqueued -= eventQueue->nevents; + } + return n_enqueued; +} + +/* Pre-condition: Called with miEventQueueMutex held */ +static Bool +mieqGrowQueue(EventQueuePtr eventQueue, size_t new_nevents) { + size_t i, n_enqueued, first_hunk; + EventRec *new_events; + + if (!eventQueue) { + ErrorF("[mi] mieqGrowQueue called with a NULL eventQueue\n"); + return FALSE; + } + + if (new_nevents <= eventQueue->nevents) + return FALSE; + + new_events = calloc(new_nevents, sizeof(EventRec)); + if (new_events == NULL) { + ErrorF("[mi] mieqGrowQueue memory allocation error.\n"); + return FALSE; + } + + n_enqueued = mieqNumEnqueued(eventQueue); + + /* We block signals, so an mieqEnqueue triggered by SIGIO does not + * write to our queue as we are modifying it. + */ + OsBlockSignals(); + + /* First copy the existing events */ + first_hunk = eventQueue->nevents - eventQueue->head; + memcpy(new_events, + &eventQueue->events[eventQueue->head], + first_hunk * sizeof(EventRec)); + memcpy(&new_events[first_hunk], + eventQueue->events, + eventQueue->head * sizeof(EventRec)); + + /* Initialize the new portion */ + for (i = eventQueue->nevents; i < new_nevents; i++) { + InternalEvent* evlist = InitEventList(1); + if (!evlist) { + size_t j; + for (j = 0; j < i; j++) + FreeEventList(new_events[j].events, 1); + free(new_events); + OsReleaseSignals(); + return FALSE; + } + new_events[i].events = evlist; + } + + /* And update our record */ + eventQueue->tail = n_enqueued; + eventQueue->head = 0; + eventQueue->nevents = new_nevents; + free(eventQueue->events); + eventQueue->events = new_events; + + OsReleaseSignals(); + return TRUE; +} + Bool mieqInit(void) { - int i; - - miEventQueue.head = miEventQueue.tail = 0; + memset(&miEventQueue, 0, sizeof(miEventQueue)); miEventQueue.lastEventTime = GetTimeInMillis (); - miEventQueue.lastMotion = FALSE; - for (i = 0; i < 128; i++) - miEventQueue.handlers[i] = NULL; - for (i = 0; i < QUEUE_SIZE; i++) - { - if (miEventQueue.events[i].events == NULL) { - InternalEvent* evlist = InitEventList(1); - if (!evlist) - FatalError("Could not allocate event queue.\n"); - miEventQueue.events[i].events = evlist; - } - } + + if(!mieqGrowQueue(&miEventQueue, QUEUE_INITIAL_SIZE)) + FatalError("Could not allocate event queue.\n"); SetInputCheck(&miEventQueue.head, &miEventQueue.tail); return TRUE; @@ -127,13 +196,34 @@ void mieqFini(void) { int i; - for (i = 0; i < QUEUE_SIZE; i++) + for (i = 0; i < miEventQueue.nevents; i++) { if (miEventQueue.events[i].events != NULL) { FreeEventList(miEventQueue.events[i].events, 1); miEventQueue.events[i].events = NULL; } } + free(miEventQueue.events); +} + +/* This function will determine if the given event is allowed to used the reserved + * queue space. + */ +static Bool +mieqReservedCandidate(InternalEvent *e) { + switch(e->any.type) { + case ET_KeyRelease: + case ET_ButtonRelease: +#if XFreeXDGA + case ET_DGAEvent: +#endif + case ET_RawKeyRelease: + case ET_RawButtonRelease: + case ET_XQuartz: + return TRUE; + default: + return FALSE; + } } /* @@ -151,6 +241,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) int isMotion = 0; int evlen; Time time; + size_t n_enqueued; #ifdef XQUARTZ wait_for_server_init(); @@ -159,32 +250,40 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) verify_internal_event(e); + n_enqueued = mieqNumEnqueued(&miEventQueue); + /* avoid merging events from different devices */ if (e->any.type == ET_Motion) isMotion = pDev->id; if (isMotion && isMotion == miEventQueue.lastMotion && oldtail != miEventQueue.head) { - oldtail = (oldtail - 1) % QUEUE_SIZE; - } - else { - static int stuck = 0; + oldtail = (oldtail - 1) % miEventQueue.nevents; + } else if ((n_enqueued + 1 == miEventQueue.nevents) || + ((n_enqueued + 1 >= miEventQueue.nevents - QUEUE_RESERVED_SIZE) && !mieqReservedCandidate(e))) { /* Toss events which come in late. Usually this means your server's * stuck in an infinite loop somewhere, but SIGIO is still getting - * handled. */ - if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) { - if (!stuck) { - ErrorF("[mi] EQ overflowing. The server is probably stuck " - "in an infinite loop.\n"); - xorg_backtrace(); - stuck = 1; + * handled. + */ + miEventQueue.dropped++; + if (miEventQueue.dropped == 1) { + ErrorF("[mi] EQ overflowing. Additional events will be discarded until existing events are processed.\n"); + xorg_backtrace(); + ErrorF("[mi] These backtraces from mieqEnqueue may point to a culprit higher up the stack.\n"); + ErrorF("[mi] mieq is *NOT* the cause. It is a victim.\n"); + } else if (miEventQueue.dropped % QUEUE_DROP_BACKTRACE_FREQUENCY == 0 && + miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY <= QUEUE_DROP_BACKTRACE_MAX) { + ErrorF("[mi] EQ overflow continuing. %lu events have been dropped.\n", miEventQueue.dropped); + if (miEventQueue.dropped / QUEUE_DROP_BACKTRACE_FREQUENCY == QUEUE_DROP_BACKTRACE_MAX) { + ErrorF("[mi] No further overflow reports will be reported until the clog is cleared.\n"); } + xorg_backtrace(); + } + #ifdef XQUARTZ - pthread_mutex_unlock(&miEventQueueMutex); + pthread_mutex_unlock(&miEventQueueMutex); #endif - return; - } - stuck = 0; + return; } evlen = e->any.length; @@ -203,7 +302,7 @@ mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) miEventQueue.events[oldtail].pDev = pDev; miEventQueue.lastMotion = isMotion; - miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE; + miEventQueue.tail = (oldtail + 1) % miEventQueue.nevents; #ifdef XQUARTZ pthread_mutex_unlock(&miEventQueueMutex); #endif @@ -437,11 +536,28 @@ mieqProcessInputEvents(void) static InternalEvent event; DeviceIntPtr dev = NULL, master = NULL; + size_t n_enqueued; #ifdef XQUARTZ pthread_mutex_lock(&miEventQueueMutex); #endif - + + /* Grow our queue if we are reaching capacity: < 2 * QUEUE_RESERVED_SIZE remaining */ + n_enqueued = mieqNumEnqueued(&miEventQueue); + if (n_enqueued >= (miEventQueue.nevents - (2 * QUEUE_RESERVED_SIZE)) && + miEventQueue.nevents < QUEUE_MAXIMUM_SIZE) { + ErrorF("[mi] Increasing EQ size to %lu to prevent dropped events.\n", miEventQueue.nevents << 1); + if (!mieqGrowQueue(&miEventQueue, miEventQueue.nevents << 1)) { + ErrorF("[mi] Increasing the size of EQ failed.\n"); + } + } + + if (miEventQueue.dropped) { + ErrorF("[mi] EQ processing has resumed after %lu dropped events.\n", miEventQueue.dropped); + ErrorF("[mi] This may be caused my a misbehaving driver monopolizing the server's resources.\n"); + miEventQueue.dropped = 0; + } + while (miEventQueue.head != miEventQueue.tail) { e = &miEventQueue.events[miEventQueue.head]; @@ -449,7 +565,7 @@ mieqProcessInputEvents(void) dev = e->pDev; screen = e->pScreen; - miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; + miEventQueue.head = (miEventQueue.head + 1) % miEventQueue.nevents; #ifdef XQUARTZ pthread_mutex_unlock(&miEventQueueMutex); diff --git a/test/input.c b/test/input.c index 347519716..5b4c8c193 100644 --- a/test/input.c +++ b/test/input.c @@ -40,6 +40,7 @@ #include "dixgrabs.h" #include "eventstr.h" #include "inpututils.h" +#include "mi.h" #include "assert.h" /** @@ -1480,8 +1481,6 @@ _test_double_fp16_values(double orig_d) { FP1616 first_fp16, final_fp16; double final_d; - char first_fp16_s[64]; - char final_fp16_s[64]; if (orig_d > 0x7FFF) { printf("Test out of range\n"); @@ -1492,10 +1491,15 @@ _test_double_fp16_values(double orig_d) final_d = fp1616_to_double(first_fp16); final_fp16 = double_to_fp1616(final_d); - snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff); - snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff); - - printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s); + /* { + * char first_fp16_s[64]; + * char final_fp16_s[64]; + * snprintf(first_fp16_s, sizeof(first_fp16_s), "%d + %u * 2^-16", (first_fp16 & 0xffff0000) >> 16, first_fp16 & 0xffff); + * snprintf(final_fp16_s, sizeof(final_fp16_s), "%d + %u * 2^-16", (final_fp16 & 0xffff0000) >> 16, final_fp16 & 0xffff); + * + * printf("FP16: original double: %f first fp16: %s, re-encoded double: %f, final fp16: %s\n", orig_d, first_fp16_s, final_d, final_fp16_s); + * } + */ /* since we lose precision, we only do rough range testing */ assert(final_d > orig_d - 0.1); @@ -1603,6 +1607,73 @@ dix_double_fp_conversion(void) } } +/* The mieq test verifies that events added to the queue come out in the same + * order that they went in. + */ +static uint32_t mieq_test_event_last_processed; + +static void +mieq_test_event_handler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) { + RawDeviceEvent *e = (RawDeviceEvent *)ie; + + assert(e->type == ET_RawMotion); + assert(e->flags > mieq_test_event_last_processed); + mieq_test_event_last_processed = e->flags; +} + +static void _mieq_test_generate_events(uint32_t start, uint32_t count) { + count += start; + while (start < count) { + RawDeviceEvent e = {0}; + e.header = ET_Internal; + e.type = ET_RawMotion; + e.length = sizeof(e); + e.time = GetTimeInMillis(); + e.flags = start; + + mieqEnqueue(NULL, (InternalEvent*)&e); + + start++; + } +} + +#define mieq_test_generate_events(c) { _mieq_test_generate_events(next, c); next += c; } + +static void +mieq_test(void) { + uint32_t next = 1; + + mieq_test_event_last_processed = 0; + mieqInit(); + mieqSetHandler(ET_RawMotion, mieq_test_event_handler); + + /* Enough to fit the buffer but trigger a grow */ + mieq_test_generate_events(180); + + /* We should resize to 512 now */ + mieqProcessInputEvents(); + + /* Some should now get dropped */ + mieq_test_generate_events(500); + + /* Tell us how many got dropped, 1024 now */ + mieqProcessInputEvents(); + + /* Now make it 2048 */ + mieq_test_generate_events(900); + mieqProcessInputEvents(); + + /* Now make it 4096 (max) */ + mieq_test_generate_events(1950); + mieqProcessInputEvents(); + + /* Now overflow one last time with the maximal queue and reach the verbosity limit */ + mieq_test_generate_events(10000); + mieqProcessInputEvents(); + + mieqFini(); +} + int main(int argc, char** argv) { dix_double_fp_conversion(); @@ -1621,6 +1692,7 @@ int main(int argc, char** argv) dix_valuator_alloc(); dix_get_master(); input_option_test(); + mieq_test(); return 0; } |