diff options
Diffstat (limited to 'xorg-server')
50 files changed, 1058 insertions, 414 deletions
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c index 494e887cd..94f46f72f 100644 --- a/xorg-server/Xi/extinit.c +++ b/xorg-server/Xi/extinit.c @@ -365,7 +365,7 @@ RESTYPE RT_INPUTCLIENT; extern XExtensionVersion XIVersion; -Mask PropagateMask[MAXDEVICES]; +Mask PropagateMask[EMASKSIZE]; /***************************************************************** * diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index 02c560216..49b33041b 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -250,13 +250,17 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) if (devid >= MAXDEVICES) return (DeviceIntPtr) NULL; - dev = - _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + - sizeof(SpriteInfoRec), - sizeof(DeviceIntRec) + - sizeof(SpriteInfoRec), - offsetof(DeviceIntRec, devPrivates), - PRIVATE_DEVICE); + dev = calloc(1, + sizeof(DeviceIntRec) + + sizeof(SpriteInfoRec)); + if (!dev) + return (DeviceIntPtr) NULL; + + if (!dixAllocatePrivates(&dev->devPrivates, PRIVATE_DEVICE)) { + free(dev); + return NULL; + } + if (!dev) return (DeviceIntPtr) NULL; @@ -286,6 +290,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) /* security creation/labeling check */ if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) { + dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE); free(dev); return NULL; } @@ -965,7 +970,8 @@ CloseDevice(DeviceIntPtr dev) free(dev->last.touches[j].valuators); free(dev->last.touches); dev->config_info = NULL; - dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); + dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE); + free(dev); } /** diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 1ed1d4863..e78c71e1c 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -3790,6 +3790,8 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , if (!pScreen)
return -1;
+ dixInitScreenSpecificPrivates(pScreen);
+
if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
free(pScreen);
return -1;
@@ -3841,6 +3843,7 @@ AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , screenInfo.screens[i] = pScreen;
screenInfo.numScreens++;
if (!(*pfnInit) (pScreen, argc, argv)) {
+ dixFreeScreenSpecificPrivates(pScreen);
dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
free(pScreen);
screenInfo.numScreens--;
diff --git a/xorg-server/dix/gc.c b/xorg-server/dix/gc.c index 0a7b5165c..afd37fe94 100644 --- a/xorg-server/dix/gc.c +++ b/xorg-server/dix/gc.c @@ -481,7 +481,7 @@ NewGCObject(ScreenPtr pScreen, int depth) { GCPtr pGC; - pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC); + pGC = dixAllocateScreenObjectWithPrivates(pScreen, GC, PRIVATE_GC); if (!pGC) { return (GCPtr) NULL; } diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c index 856622f5e..b8ee88f18 100644 --- a/xorg-server/dix/main.c +++ b/xorg-server/dix/main.c @@ -378,6 +378,7 @@ main(int argc, char *argv[], char *envp[]) FreeScratchPixmapsForScreen(screenInfo.screens[i]); FreeGCperDepth(i); FreeDefaultStipple(i); + dixFreeScreenSpecificPrivates(screenInfo.screens[i]); (*screenInfo.screens[i]->CloseScreen) (screenInfo.screens[i]); dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN); free(screenInfo.screens[i]); diff --git a/xorg-server/dix/pixmap.c b/xorg-server/dix/pixmap.c index 545ff54ac..0c85c3fb1 100644 --- a/xorg-server/dix/pixmap.c +++ b/xorg-server/dix/pixmap.c @@ -88,7 +88,7 @@ CreateScratchPixmapsForScreen(ScreenPtr pScreen) { unsigned int pixmap_size; - pixmap_size = sizeof(PixmapRec) + dixPrivatesSize(PRIVATE_PIXMAP); + pixmap_size = sizeof(PixmapRec) + dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP); pScreen->totalPixmapSize = BitmapBytePad(pixmap_size * 8); @@ -118,7 +118,7 @@ AllocatePixmap(ScreenPtr pScreen, int pixDataSize) if (!pPixmap) return NullPixmap; - dixInitPrivates(pPixmap, pPixmap + 1, PRIVATE_PIXMAP); + dixInitScreenPrivates(pScreen, pPixmap, pPixmap + 1, PRIVATE_PIXMAP); return pPixmap; } diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c index 21faf5b94..04fa24ad3 100644 --- a/xorg-server/dix/privates.c +++ b/xorg-server/dix/privates.c @@ -62,13 +62,9 @@ from The Open Group. #include "inputstr.h" #include "scrnintstr.h" #include "extnsionst.h" +#include "inputstr.h" -static struct { - DevPrivateKey key; - unsigned offset; - int created; - int allocated; -} keys[PRIVATE_LAST]; +static DevPrivateSetRec global_keys[PRIVATE_LAST]; static const Bool xselinux_private[PRIVATE_LAST] = { /* PRIVATE_XSELINUX,*/ FALSE, @@ -91,8 +87,63 @@ static const Bool xselinux_private[PRIVATE_LAST] = { /* [PRIVATE_PICTURE] =*/ TRUE }; +static const char *key_names[PRIVATE_LAST] = { + /* XSELinux uses the same private keys for numerous objects */ + /*[PRIVATE_XSELINUX] =*/ "XSELINUX", + + /* Otherwise, you get a private in just the requested structure + */ + /* These can have objects created before all of the keys are registered */ + /*[PRIVATE_SCREEN] =*/ "SCREEN", + /*[PRIVATE_EXTENSION] =*/ "EXTENSION", + /*[PRIVATE_COLORMAP] =*/ "COLORMAP", + /*[PRIVATE_DEVICE] =*/ "DEVICE", + + /* These cannot have any objects before all relevant keys are registered */ + /*[PRIVATE_CLIENT] =*/ "CLIENT", + /*[PRIVATE_PROPERTY] =*/ "PROPERTY", + /*[PRIVATE_SELECTION] =*/ "SELECTION", + /*[PRIVATE_WINDOW] =*/ "WINDOW", + /*[PRIVATE_PIXMAP] =*/ "PIXMAP", + /*[PRIVATE_GC] =*/ "GC", + /*[PRIVATE_CURSOR] =*/ "CURSOR", + /*[PRIVATE_CURSOR_BITS] =*/ "CURSOR_BITS", + + /* extension privates */ + /*[PRIVATE_DBE_WINDOW] =*/ "DBE_WINDOW", + /*[PRIVATE_DAMAGE] =*/ "DAMAGE", + /*[PRIVATE_GLYPH] =*/ "GLYPH", + /*[PRIVATE_GLYPHSET] =*/ "GLYPHSET", + /*[PRIVATE_PICTURE] =*/ "PICTURE", + /*[PRIVATE_SYNC_FENCE] =*/ "SYNC_FENCE", +}; + +static const Bool screen_specific_private[PRIVATE_LAST] = { + /*[PRIVATE_XSELINUX] =*/ FALSE, + /*[PRIVATE_SCREEN] =*/ FALSE, + /*[PRIVATE_EXTENSION] =*/ FALSE, + /*[PRIVATE_COLORMAP] =*/ FALSE, + /*[PRIVATE_DEVICE] =*/ FALSE, + /*[PRIVATE_CLIENT] =*/ FALSE, + /*[PRIVATE_PROPERTY] =*/ FALSE, + /*[PRIVATE_SELECTION] =*/ FALSE, + /*[PRIVATE_WINDOW] =*/ TRUE, + /*[PRIVATE_PIXMAP] =*/ TRUE, + /*[PRIVATE_GC] =*/ TRUE, + /*[PRIVATE_CURSOR] =*/ FALSE, + /*[PRIVATE_CURSOR_BITS] =*/ FALSE, + /*[PRIVATE_DBE_WINDOW] =*/ FALSE, + /*[PRIVATE_DAMAGE] =*/ FALSE, + /*[PRIVATE_GLYPH] =*/ FALSE, + /*[PRIVATE_GLYPHSET] =*/ FALSE, + /*[PRIVATE_PICTURE] =*/ TRUE, + /*[PRIVATE_SYNC_FENCE] =*/ FALSE +}; + typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes); +typedef enum { FixupMove, FixupRealloc } FixupType; + static Bool dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes) { @@ -115,14 +166,72 @@ dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes) } static Bool +fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes) +{ + intptr_t dist; + char *old; + char *new; + DevPrivateKey *keyp, key; + DevPrivateType type; + int size; + + old = (char *) pScreen->devPrivates; + size = global_keys[PRIVATE_SCREEN].offset; + if (!fixup (&pScreen->devPrivates, size, bytes)) + return FALSE; + + /* Screen privates can contain screen-specific private keys + * for other types. When they move, the linked list we use to + * track them gets scrambled. Fix that by computing the change + * in the location of each private adjusting our linked list + * pointers to match + */ + + new = (char *) pScreen->devPrivates; + + /* Moving means everyone shifts up in the privates by 'bytes' amount, + * realloc means the base pointer moves + */ + if (fixup == dixMovePrivates) + new += bytes; + + dist = new - old; + + if (dist) { + for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++) + + /* Walk the privates list, being careful as the + * pointers are scrambled before we patch them. + */ + for (keyp = &pScreen->screenSpecificPrivates[type].key; + (key = *keyp) != NULL; + keyp = &key->next) + { + + /* Only mangle things if the private structure + * is contained within the allocation. Privates + * stored elsewhere will be left alone + */ + if (old <= (char *) key && (char *) key < old + size) + { + /* Compute new location of key */ + key = (DevPrivateKey) ((char *) key + dist); + + /* Patch the list */ + *keyp = key; + } + } + } + return TRUE; +} + +static Bool fixupScreens(FixupFunc fixup, unsigned bytes) { int s; for (s = 0; s < screenInfo.numScreens; s++) - if (!fixup - (&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, - bytes)) + if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes)) return FALSE; return TRUE; } @@ -131,7 +240,7 @@ static Bool fixupServerClient(FixupFunc fixup, unsigned bytes) { if (serverClient) - return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, + return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset, bytes); return TRUE; } @@ -145,7 +254,7 @@ fixupExtensions(FixupFunc fixup, unsigned bytes) for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++) if (!fixup - (&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes)) + (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes)) return FALSE; return TRUE; } @@ -162,19 +271,37 @@ fixupDefaultColormaps(FixupFunc fixup, unsigned bytes) screenInfo.screens[s]->defColormap, RT_COLORMAP, serverClient, DixCreateAccess); if (cmap && - !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes)) + !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes)) return FALSE; } return TRUE; } +static Bool +fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes) +{ + while (device) { + if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes)) + return FALSE; + device = device->next; + } + return TRUE; +} + +static Bool +fixupDevices(FixupFunc fixup, unsigned bytes) +{ + return (fixupDeviceList(inputInfo.devices, fixup, bytes) && + fixupDeviceList(inputInfo.off_devices, fixup, bytes)); +} + static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { /*PRIVATE_XSELINUX,*/ NULL, - /*[PRIVATE_SCREEN] =*/ fixupScreens, - /*[PRIVATE_EXTENSION] =*/ fixupExtensions, - /*[PRIVATE_COLORMAP] =*/ fixupDefaultColormaps, - /*PRIVATE_DEVICE,*/ NULL, - /*[PRIVATE_CLIENT] =*/ fixupServerClient, + /*PRIVATE_SCREEN =*/ fixupScreens, + /*PRIVATE_EXTENSION =*/ fixupExtensions, + /*PRIVATE_COLORMAP =*/ fixupDefaultColormaps, + /*PRIVATE_DEVICE,*/ fixupDevices, + /*PRIVATE_CLIENT =*/ fixupServerClient, /*PRIVATE_PROPERTY,*/ NULL, /*PRIVATE_SELECTION,*/ NULL, /*PRIVATE_WINDOW,*/ NULL, @@ -186,9 +313,33 @@ static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { /*PRIVATE_DAMAGE,*/ NULL, /*PRIVATE_GLYPH,*/ NULL, /*PRIVATE_GLYPHSET,*/ NULL, - /*PRIVATE_PICTURE,*/ NULL + /*PRIVATE_PICTURE,*/ NULL, + /*PRIVATE_SYNC_FENCE,*/ NULL }; +static void +grow_private_set(DevPrivateSetPtr set, unsigned bytes) +{ + DevPrivateKey k; + + for (k = set->key; k; k = k->next) + k->offset += bytes; + set->offset += bytes; +} + +static void +grow_screen_specific_set(DevPrivateType type, unsigned bytes) +{ + int s; + + /* Update offsets for all screen-specific keys */ + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr pScreen = screenInfo.screens[s]; + + grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); + } +} + /* * Register a private key. This takes the type of object the key will * be used with, which may be PRIVATE_ALL indicating that this key @@ -219,14 +370,13 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) /* Update offsets for all affected keys */ if (type == PRIVATE_XSELINUX) { - DevPrivateKey k; /* Resize if we can, or make sure nothing's allocated if we can't */ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) if (xselinux_private[t]) { if (!allocated_early[t]) - assert(!keys[t].created); + assert(!global_keys[t].created); else if (!allocated_early[t] (dixReallocPrivates, bytes)) return FALSE; } @@ -236,12 +386,12 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) */ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { if (xselinux_private[t]) { - for (k = keys[t].key; k; k = k->next) - k->offset += bytes; - keys[t].offset += bytes; + grow_private_set(&global_keys[t], bytes); + grow_screen_specific_set(t, bytes); if (allocated_early[t]) allocated_early[t] (dixMovePrivates, bytes); } + } offset = 0; @@ -249,11 +399,12 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) else { /* Resize if we can, or make sure nothing's allocated if we can't */ if (!allocated_early[type]) - assert(!keys[type].created); + assert(!global_keys[type].created); else if (!allocated_early[type] (dixReallocPrivates, bytes)) return FALSE; - offset = keys[type].offset; - keys[type].offset += bytes; + offset = global_keys[type].offset; + global_keys[type].offset += bytes; + grow_screen_specific_set(type, bytes); } /* Setup this key */ @@ -262,8 +413,8 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) key->initialized = TRUE; key->type = type; key->allocated = FALSE; - key->next = keys[type].key; - keys[type].key = key; + key->next = global_keys[type].key; + global_keys[type].key = key; return TRUE; } @@ -306,13 +457,15 @@ _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen) void _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) { - keys[type].created++; + assert (!screen_specific_private[type]); + + global_keys[type].created++; if (xselinux_private[type]) - keys[PRIVATE_XSELINUX].created++; - if (keys[type].offset == 0) + global_keys[PRIVATE_XSELINUX].created++; + if (global_keys[type].offset == 0) addr = 0; *privates = addr; - memset(addr, '\0', keys[type].offset); + memset(addr, '\0', global_keys[type].offset); } /* @@ -321,9 +474,9 @@ _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) void _dixFiniPrivates(PrivatePtr privates, DevPrivateType type) { - keys[type].created--; + global_keys[type].created--; if (xselinux_private[type]) - keys[PRIVATE_XSELINUX].created--; + global_keys[PRIVATE_XSELINUX].created--; } /* @@ -342,10 +495,11 @@ _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, PrivatePtr *devPrivates; assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); + assert(!screen_specific_private[type]); /* round up so that void * is aligned */ baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); - totalSize = baseSize + keys[type].offset; + totalSize = baseSize + global_keys[type].offset; object = malloc(totalSize); if (!object) return NULL; @@ -370,8 +524,9 @@ dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) PrivatePtr p; assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST); + assert(!screen_specific_private[type]); - size = keys[type].offset; + size = global_keys[type].offset; if (!size) { p = NULL; } @@ -381,7 +536,7 @@ dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) } _dixInitPrivates(privates, p, type); - ++keys[type].allocated; + ++global_keys[type].allocated; return TRUE; } @@ -407,7 +562,7 @@ void dixFreePrivates(PrivatePtr privates, DevPrivateType type) { _dixFiniPrivates(privates, type); - --keys[type].allocated; + --global_keys[type].allocated; free(privates); } @@ -418,8 +573,9 @@ extern _X_EXPORT int dixPrivatesSize(DevPrivateType type) { assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); + assert (!screen_specific_private[type]); - return keys[type].offset; + return global_keys[type].offset; } /* Table of devPrivates offsets */ @@ -454,36 +610,136 @@ dixLookupPrivateOffset(RESTYPE type) return -1; } -static const char *key_names[PRIVATE_LAST] = { - /* XSELinux uses the same private keys for numerous objects */ - /*[PRIVATE_XSELINUX] =*/ "XSELINUX", +/* + * Screen-specific privates + */ - /* Otherwise, you get a private in just the requested structure - */ - /* These can have objects created before all of the keys are registered */ - /*[PRIVATE_SCREEN] =*/ "SCREEN", - /*[PRIVATE_EXTENSION] =*/ "EXTENSION", - /*[PRIVATE_COLORMAP] =*/ "COLORMAP", +extern _X_EXPORT Bool +dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, + DevPrivateType type, unsigned size) +{ + int offset; + unsigned bytes; - /* These cannot have any objects before all relevant keys are registered */ - /*[PRIVATE_DEVICE] =*/ "DEVICE", - /*[PRIVATE_CLIENT] =*/ "CLIENT", - /*[PRIVATE_PROPERTY] =*/ "PROPERTY", - /*[PRIVATE_SELECTION] =*/ "SELECTION", - /*[PRIVATE_WINDOW] =*/ "WINDOW", - /*[PRIVATE_PIXMAP] =*/ "PIXMAP", - /*[PRIVATE_GC] =*/ "GC", - /*[PRIVATE_CURSOR] =*/ "CURSOR", - /*[PRIVATE_CURSOR_BITS] =*/ "CURSOR_BITS", + if (!screen_specific_private[type]) + FatalError("Attempt to allocate screen-specific private storage for type %s\n", + key_names[type]); - /* extension privates */ - /*[PRIVATE_DBE_WINDOW] =*/ "DBE_WINDOW", - /*[PRIVATE_DAMAGE] =*/ "DAMAGE", - /*[PRIVATE_GLYPH] =*/ "GLYPH", - /*[PRIVATE_GLYPHSET] =*/ "GLYPHSET", - /*[PRIVATE_PICTURE] =*/ "PICTURE" , - /*[PRIVATE_SYNC_FENCE] =*/ "SYNC_FENCE" -}; + if (key->initialized) { + assert(size == key->size); + return TRUE; + } + + /* Compute required space */ + bytes = size; + if (size == 0) + bytes = sizeof(void *); + + /* align to void * size */ + bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); + + assert (!allocated_early[type]); + assert (!pScreen->screenSpecificPrivates[type].created); + offset = pScreen->screenSpecificPrivates[type].offset; + pScreen->screenSpecificPrivates[type].offset += bytes; + + /* Setup this key */ + key->offset = offset; + key->size = size; + key->initialized = TRUE; + key->type = type; + key->allocated = FALSE; + key->next = pScreen->screenSpecificPrivates[type].key; + pScreen->screenSpecificPrivates[type].key = key; + + return TRUE; +} + +/* Clean up screen-specific privates before CloseScreen */ +void +dixFreeScreenSpecificPrivates(ScreenPtr pScreen) +{ +} + +/* Initialize screen-specific privates in AddScreen */ +void +dixInitScreenSpecificPrivates(ScreenPtr pScreen) +{ + DevPrivateType t; + + for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) + pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset; +} + +/* Initialize screen-specific privates in AddScreen */ +void +_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type) +{ + int privates_size; + assert (screen_specific_private[type]); + + if (pScreen) { + privates_size = pScreen->screenSpecificPrivates[type].offset; + pScreen->screenSpecificPrivates[type].created++; + } + else + privates_size = global_keys[type].offset; + + global_keys[type].created++; + if (xselinux_private[type]) + global_keys[PRIVATE_XSELINUX].created++; + if (privates_size == 0) + addr = 0; + *privates = addr; + memset(addr, '\0', privates_size); +} + +void * +_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen, + unsigned baseSize, + unsigned clear, + unsigned offset, + DevPrivateType type) +{ + unsigned totalSize; + void *object; + PrivatePtr privates; + PrivatePtr *devPrivates; + int privates_size; + + assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); + assert (screen_specific_private[type]); + + if (pScreen) + privates_size = pScreen->screenSpecificPrivates[type].offset; + else + privates_size = global_keys[type].offset; + /* round up so that void * is aligned */ + baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); + totalSize = baseSize + privates_size; + object = malloc(totalSize); + if (!object) + return NULL; + + memset(object, '\0', clear); + privates = (PrivatePtr) (((char *) object) + baseSize); + devPrivates = (PrivatePtr *) ((char *) object + offset); + + _dixInitScreenPrivates(pScreen, devPrivates, privates, type); + + return object; +} + +int +dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type) +{ + assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); + + if (screen_specific_private[type]) + return pScreen->screenSpecificPrivates[type].offset; + else + return global_keys[type].offset; +} void dixPrivateUsage(void) @@ -494,14 +750,14 @@ dixPrivateUsage(void) DevPrivateType t; for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) { - if (keys[t].offset) { + if (global_keys[t].offset) { ErrorF ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n", - key_names[t], keys[t].created, keys[t].offset, - keys[t].created * keys[t].offset, keys[t].allocated); - bytes += keys[t].created * keys[t].offset; - objects += keys[t].created; - alloc += keys[t].allocated; + key_names[t], global_keys[t].created, global_keys[t].offset, + global_keys[t].created * global_keys[t].offset, global_keys[t].allocated); + bytes += global_keys[t].created * global_keys[t].offset; + objects += global_keys[t].created; + alloc += global_keys[t].allocated; } } ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc); @@ -515,7 +771,7 @@ dixResetPrivates(void) for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { DevPrivateKey key, next; - for (key = keys[t].key; key; key = next) { + for (key = global_keys[t].key; key; key = next) { next = key->next; key->offset = 0; key->initialized = FALSE; @@ -524,14 +780,14 @@ dixResetPrivates(void) if (key->allocated) free(key); } - if (keys[t].created) { + if (global_keys[t].created) { ErrorF("%d %ss still allocated at reset\n", - keys[t].created, key_names[t]); + global_keys[t].created, key_names[t]); dixPrivateUsage(); } - keys[t].key = NULL; - keys[t].offset = 0; - keys[t].created = 0; - keys[t].allocated = 0; + global_keys[t].key = NULL; + global_keys[t].offset = 0; + global_keys[t].created = 0; + global_keys[t].allocated = 0; } } diff --git a/xorg-server/dix/touch.c b/xorg-server/dix/touch.c index a01f152cd..497ad7dac 100644 --- a/xorg-server/dix/touch.c +++ b/xorg-server/dix/touch.c @@ -160,11 +160,13 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id) int i; TouchClassPtr t = dev->touch; DDXTouchPointInfoPtr ti = NULL; - Bool emulate_pointer = (t->mode == XIDirectTouch); + Bool emulate_pointer; if (!t) return NULL; + emulate_pointer = (t->mode == XIDirectTouch); + /* Look for another active touchpoint with the same DDX ID. DDX * touchpoints must be unique. */ if (TouchFindByDDXID(dev, ddx_id, FALSE)) @@ -461,14 +463,17 @@ TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev) void TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource) { - InternalEvent *tel = InitEventList(GetMaximumEventsNum()); - ValuatorMask *mask = valuator_mask_new(0); + InternalEvent *tel; + ValuatorMask *mask; int i, nev; int flags; if (!ti->history) return; + tel = InitEventList(GetMaximumEventsNum()); + mask = valuator_mask_new(0); + valuator_mask_set_double(mask, 0, ti->history[0].valuators.data[0]); valuator_mask_set_double(mask, 1, ti->history[0].valuators.data[1]); diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c index 5cc3a502d..b66080830 100644 --- a/xorg-server/dix/window.c +++ b/xorg-server/dix/window.c @@ -446,7 +446,7 @@ CreateRootWindow(ScreenPtr pScreen) BoxRec box; PixmapFormatRec *format; - pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW); + pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW); if (!pWin) return FALSE; @@ -710,7 +710,7 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, return NullWindow; } - pWin = dixAllocateObjectWithPrivates(WindowRec, PRIVATE_WINDOW); + pWin = dixAllocateScreenObjectWithPrivates(pScreen, WindowRec, PRIVATE_WINDOW); if (!pWin) { *error = BadAlloc; return NullWindow; diff --git a/xorg-server/doc/Xserver-spec.xml b/xorg-server/doc/Xserver-spec.xml index 31b6fb05d..cd1a9d07a 100644 --- a/xorg-server/doc/Xserver-spec.xml +++ b/xorg-server/doc/Xserver-spec.xml @@ -109,6 +109,12 @@ <revremark>Revised for Xorg 1.9 devPrivates changes and 1.8 CreateNewResourceType changes</revremark> </revision> + <revision> + <revnumber>3.6</revnumber> + <date>July 2012</date> + <authorinitials>kp</authorinitials> + <revremark>Revised for X server 1.13 screen-specific devPrivates changes</revremark> + </revision> </revhistory> <abstract> <para>The following document explains the structure of the X Window System display server and the interfaces among the larger pieces. It is intended as a reference for programmers who are implementing an X Display Server on their workstation hardware. It is included with the X Window System source tape, along with the document "Strategies for Porting the X v11 Sample Server." The order in which you should read these documents is: @@ -4714,7 +4720,8 @@ Two new extensibility concepts have been developed for release 4, Wrappers and devPrivates. These replace the R3 GCInterest queues, which were not a general enough mechanism for many extensions and only provided hooks into a single data structure. devPrivates have been revised substantially for -X.Org X server release 1.5, and updated again for the 1.9 release.</para> +X.Org X server release 1.5, updated again for the 1.9 release and extended +again for the 1.13 relealse.</para> <section> <title>devPrivates</title> <para> @@ -4758,6 +4765,23 @@ the specified type with distinct storage for the given that are otherwise equivalent to the following Private functions.</para> <para> + To request private space in objects created for a specific screen, use + <blockquote><programlisting> + Bool dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, DevPrivateType type, unsigned size); + </programlisting></blockquote> + The <parameter>type</parameter> and <parameter>size</parameter> arguments are + the same as those to <function>dixRegisterPrivateKey</function> but this + function ensures only that the given <parameter>key</parameter> exists on objects of + the specified type that are allocated with reference to the specified + <parameter>pScreen</parameter>. Using the key on objects allocated for + other screens will result in incorrect results; there is no check made to + ensure that the caller's screen matches the private's screen. The key is + usable in any of the following functions. Screen-specific private storage is available + only for Windows, GCs, Pixmaps and Pictures. Attempts to allocate screen-specific + privates on other objects will result in a call to FatalError. +</para> + +<para> To attach a piece of private data to an object, use: <blockquote><programlisting> void dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) diff --git a/xorg-server/exa/exa.c b/xorg-server/exa/exa.c index 0f90e593c..623ece073 100644 --- a/xorg-server/exa/exa.c +++ b/xorg-server/exa/exa.c @@ -38,8 +38,6 @@ #include "exa.h" DevPrivateKeyRec exaScreenPrivateKeyRec; -DevPrivateKeyRec exaPixmapPrivateKeyRec; -DevPrivateKeyRec exaGCPrivateKeyRec; #ifdef MITSHM static ShmFuncs exaShmFuncs = { NULL, NULL }; @@ -915,8 +913,8 @@ exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo) exaDDXDriverInit(pScreen); - if (!dixRegisterPrivateKey - (&exaGCPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { + if (!dixRegisterScreenSpecificPrivateKey + (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n", pScreen->myNum); return FALSE; @@ -964,8 +962,8 @@ exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo) * Hookup offscreen pixmaps */ if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { - if (!dixRegisterPrivateKey - (&exaPixmapPrivateKeyRec, PRIVATE_PIXMAP, + if (!dixRegisterScreenSpecificPrivateKey + (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP, sizeof(ExaPixmapPrivRec))) { LogMessage(X_WARNING, "EXA(%d): Failed to allocate pixmap private\n", diff --git a/xorg-server/exa/exa_priv.h b/xorg-server/exa/exa_priv.h index f980fea6d..68eadc550 100644 --- a/xorg-server/exa/exa_priv.h +++ b/xorg-server/exa/exa_priv.h @@ -208,6 +208,8 @@ typedef struct { RegionRec maskReg; PixmapPtr srcPix; + DevPrivateKeyRec pixmapPrivateKeyRec; + DevPrivateKeyRec gcPrivateKeyRec; } ExaScreenPrivRec, *ExaScreenPrivPtr; /* @@ -225,17 +227,11 @@ typedef struct { extern DevPrivateKeyRec exaScreenPrivateKeyRec; #define exaScreenPrivateKey (&exaScreenPrivateKeyRec) -extern DevPrivateKeyRec exaPixmapPrivateKeyRec; - -#define exaPixmapPrivateKey (&exaPixmapPrivateKeyRec) -extern DevPrivateKeyRec exaGCPrivateKeyRec; - -#define exaGCPrivateKey (&exaGCPrivateKeyRec) #define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)dixGetPrivate(&(s)->devPrivates, exaScreenPrivateKey)) #define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s) -#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixGetPrivateAddr(&(gc)->devPrivates, exaGCPrivateKey)) +#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixGetPrivateAddr(&(gc)->devPrivates, &ExaGetScreenPriv(gc->pScreen)->gcPrivateKeyRec)) #define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc) /* @@ -286,7 +282,7 @@ extern DevPrivateKeyRec exaGCPrivateKeyRec; #define EXA_PIXMAP_SCORE_PINNED 1000 #define EXA_PIXMAP_SCORE_INIT 1001 -#define ExaGetPixmapPriv(p) ((ExaPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, exaPixmapPrivateKey)) +#define ExaGetPixmapPriv(p) ((ExaPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &ExaGetScreenPriv((p)->drawable.pScreen)->pixmapPrivateKeyRec)) #define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p) #define EXA_RANGE_PITCH (1 << 0) diff --git a/xorg-server/fb/fb.h b/xorg-server/fb/fb.h index 613af78e9..1b0b638ba 100644 --- a/xorg-server/fb/fb.h +++ b/xorg-server/fb/fb.h @@ -570,12 +570,6 @@ extern _X_EXPORT void fbSetBits(FbStip * bits, int stride, FbStip data); } \ } -extern _X_EXPORT DevPrivateKey - fbGetGCPrivateKey(void); - -extern _X_EXPORT DevPrivateKey - fbGetWinPrivateKey(void); - extern _X_EXPORT const GCOps fbGCOps; extern _X_EXPORT const GCFuncs fbGCFuncs; @@ -605,7 +599,7 @@ typedef void (*FinishWrapProcPtr) (DrawablePtr pDraw); #endif extern _X_EXPORT DevPrivateKey - fbGetScreenPrivateKey(void); +fbGetScreenPrivateKey(void); /* private field of a screen */ typedef struct { @@ -615,6 +609,8 @@ typedef struct { SetupWrapProcPtr setupWrap; /* driver hook to set pixmap access wrapping */ FinishWrapProcPtr finishWrap; /* driver hook to clean up pixmap access wrapping */ #endif + DevPrivateKeyRec gcPrivateKeyRec; + DevPrivateKeyRec winPrivateKeyRec; } FbScreenPrivRec, *FbScreenPrivPtr; #define fbGetScreenPrivate(pScreen) ((FbScreenPrivPtr) \ @@ -630,8 +626,10 @@ typedef struct { unsigned char bpp; /* current drawable bpp */ } FbGCPrivRec, *FbGCPrivPtr; +#define fbGetGCPrivateKey(pGC) (&fbGetScreenPrivate((pGC)->pScreen)->gcPrivateKeyRec) + #define fbGetGCPrivate(pGC) ((FbGCPrivPtr)\ - dixLookupPrivate(&(pGC)->devPrivates, fbGetGCPrivateKey())) + dixLookupPrivate(&(pGC)->devPrivates, fbGetGCPrivateKey(pGC))) #define fbGetCompositeClip(pGC) ((pGC)->pCompositeClip) #define fbGetExpose(pGC) ((pGC)->fExpose) @@ -639,8 +637,11 @@ typedef struct { #define fbGetRotatedPixmap(pGC) ((pGC)->pRotatedPixmap) #define fbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivate) + +#define fbGetWinPrivateKey(pWin) (&fbGetScreenPrivate(((DrawablePtr) (pWin))->pScreen)->winPrivateKeyRec) + #define fbGetWindowPixmap(pWin) ((PixmapPtr)\ - dixLookupPrivate(&((WindowPtr)(pWin))->devPrivates, fbGetWinPrivateKey())) + dixLookupPrivate(&((WindowPtr)(pWin))->devPrivates, fbGetWinPrivateKey(pWin))) #ifdef ROOTLESS #define __fbPixDrawableX(pPix) ((pPix)->drawable.x) @@ -782,14 +783,14 @@ fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, * fballpriv.c */ extern _X_EXPORT Bool - fbAllocatePrivates(ScreenPtr pScreen, DevPrivateKey *pGCIndex); +fbAllocatePrivates(ScreenPtr pScreen); /* * fbarc.c */ extern _X_EXPORT void - fbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs); +fbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs); /* * fbbits.c diff --git a/xorg-server/fb/fballpriv.c b/xorg-server/fb/fballpriv.c index c6504f915..187d0b068 100644 --- a/xorg-server/fb/fballpriv.c +++ b/xorg-server/fb/fballpriv.c @@ -33,33 +33,20 @@ fbGetScreenPrivateKey(void) return &fbScreenPrivateKeyRec; } -static DevPrivateKeyRec fbGCPrivateKeyRec; -DevPrivateKey -fbGetGCPrivateKey(void) -{ - return &fbGCPrivateKeyRec; -} - -static DevPrivateKeyRec fbWinPrivateKeyRec; -DevPrivateKey -fbGetWinPrivateKey(void) -{ - return &fbWinPrivateKeyRec; -} - Bool -fbAllocatePrivates(ScreenPtr pScreen, DevPrivateKey *pGCKey) +fbAllocatePrivates(ScreenPtr pScreen) { - if (pGCKey) - *pGCKey = &fbGCPrivateKeyRec; + FbScreenPrivPtr pScrPriv; if (!dixRegisterPrivateKey - (&fbGCPrivateKeyRec, PRIVATE_GC, sizeof(FbGCPrivRec))) - return FALSE; - if (!dixRegisterPrivateKey (&fbScreenPrivateKeyRec, PRIVATE_SCREEN, sizeof(FbScreenPrivRec))) return FALSE; - if (!dixRegisterPrivateKey(&fbWinPrivateKeyRec, PRIVATE_WINDOW, 0)) + + pScrPriv = fbGetScreenPrivate(pScreen); + + if (!dixRegisterScreenSpecificPrivateKey (pScreen, &pScrPriv->gcPrivateKeyRec, PRIVATE_GC, sizeof(FbGCPrivRec))) + return FALSE; + if (!dixRegisterScreenSpecificPrivateKey (pScreen, &pScrPriv->winPrivateKeyRec, PRIVATE_WINDOW, 0)) return FALSE; return TRUE; diff --git a/xorg-server/fb/fboverlay.c b/xorg-server/fb/fboverlay.c index a882ffa39..c6802e4b4 100644 --- a/xorg-server/fb/fboverlay.c +++ b/xorg-server/fb/fboverlay.c @@ -63,7 +63,7 @@ fbOverlayCreateWindow(WindowPtr pWin) for (i = 0; i < pScrPriv->nlayers; i++) { pPixmap = pScrPriv->layer[i].u.run.pixmap; if (pWin->drawable.depth == pPixmap->drawable.depth) { - dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), pPixmap); + dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), pPixmap); /* * Make sure layer keys are written correctly by * having non-root layers set to full while the @@ -103,7 +103,7 @@ fbOverlayWindowLayer(WindowPtr pWin) int i; for (i = 0; i < pScrPriv->nlayers; i++) - if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey()) == + if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin)) == (pointer) pScrPriv->layer[i].u.run.pixmap) return i; return 0; diff --git a/xorg-server/fb/fbscreen.c b/xorg-server/fb/fbscreen.c index 0833cd41e..7c7d6560e 100644 --- a/xorg-server/fb/fbscreen.c +++ b/xorg-server/fb/fbscreen.c @@ -85,7 +85,7 @@ _fbGetWindowPixmap(WindowPtr pWindow) void _fbSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap) { - dixSetPrivate(&pWindow->devPrivates, fbGetWinPrivateKey(), pPixmap); + dixSetPrivate(&pWindow->devPrivates, fbGetWinPrivateKey(pWindow), pPixmap); } Bool @@ -95,7 +95,7 @@ fbSetupScreen(ScreenPtr pScreen, pointer pbits, /* pointer to screen bitmap */ int dpiy, int width, /* pixel width of frame buffer */ int bpp) { /* bits per pixel for screen */ - if (!fbAllocatePrivates(pScreen, NULL)) + if (!fbAllocatePrivates(pScreen)) return FALSE; pScreen->defColormap = FakeClientID(0); /* let CreateDefColormap do whatever it wants for pixels */ diff --git a/xorg-server/fb/fbwindow.c b/xorg-server/fb/fbwindow.c index d27ccd4d5..368c4b883 100644 --- a/xorg-server/fb/fbwindow.c +++ b/xorg-server/fb/fbwindow.c @@ -31,7 +31,7 @@ Bool fbCreateWindow(WindowPtr pWin) { - dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), + dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), fbGetScreenPixmap(pWin->drawable.pScreen)); if (pWin->drawable.bitsPerPixel == 32) pWin->drawable.bitsPerPixel = diff --git a/xorg-server/fb/wfbrename.h b/xorg-server/fb/wfbrename.h index 1a072045e..24db14293 100644 --- a/xorg-server/fb/wfbrename.h +++ b/xorg-server/fb/wfbrename.h @@ -67,15 +67,11 @@ #define fbFixCoordModePrevious wfbFixCoordModePrevious #define fbGCFuncs wfbGCFuncs #define fbGCOps wfbGCOps -#define fbGCPrivateKeyRec wfbGCPrivateKeyRec #define fbGeneration wfbGeneration -#define fbGetGCPrivateKey wfbGetGCPrivateKey #define fbGetImage wfbGetImage #define fbGetScreenPrivateKey wfbGetScreenPrivateKey #define fbGetSpans wfbGetSpans #define _fbGetWindowPixmap _wfbGetWindowPixmap -#define fbWinPrivateKeyRec wfbWinPrivateKeyRec -#define fbGetWinPrivateKey wfbGetWinPrivateKey #define fbGlyph16 wfbGlyph16 #define fbGlyph24 wfbGlyph24 #define fbGlyph32 wfbGlyph32 diff --git a/xorg-server/glx/clientinfo.c b/xorg-server/glx/clientinfo.c index b26ac1a72..4aaa4c967 100644 --- a/xorg-server/glx/clientinfo.c +++ b/xorg-server/glx/clientinfo.c @@ -29,10 +29,10 @@ #include "glxbyteorder.h" #include "unpack.h" -int -__glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) +static int +set_client_info(__GLXclientState * cl, xGLXSetClientInfoARBReq * req, + unsigned bytes_per_version) { - xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc; char *gl_extensions; char *glx_extensions; @@ -40,7 +40,7 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) * sizes specified for the various fields. */ const unsigned expected_size = sz_xGLXSetClientInfoARBReq - + (req->numVersions * 8) + + (req->numVersions * bytes_per_version) + __GLX_PAD(req->numGLExtensionBytes) + __GLX_PAD(req->numGLXExtensionBytes); @@ -50,7 +50,7 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) /* Verify that the actual length of the GL extension string matches what's * encoded in protocol packet. */ - gl_extensions = (char *) (req + 1) + (req->numVersions * 8); + gl_extensions = (char *) (req + 1) + (req->numVersions * bytes_per_version); if (req->numGLExtensionBytes != 0 && memchr(gl_extensions, 0, __GLX_PAD(req->numGLExtensionBytes)) == NULL) @@ -72,6 +72,12 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) } int +__glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) +{ + return set_client_info(cl, (xGLXSetClientInfoARBReq *) pc, 8); +} + +int __glXDispSwap_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) { xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc; @@ -87,11 +93,18 @@ __glXDispSwap_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) int __glXDisp_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc) { - return BadRequest; + return set_client_info(cl, (xGLXSetClientInfoARBReq *) pc, 12); } int __glXDispSwap_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc) { - return BadRequest; + xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc; + + req->length = bswap_16(req->length); + req->numVersions = bswap_32(req->numVersions); + req->numGLExtensionBytes = bswap_32(req->numGLExtensionBytes); + req->numGLXExtensionBytes = bswap_32(req->numGLXExtensionBytes); + + return __glXDisp_SetClientInfo2ARB(cl, pc); } diff --git a/xorg-server/glx/createcontext.c b/xorg-server/glx/createcontext.c index 025c423fe..13d21ccb9 100644 --- a/xorg-server/glx/createcontext.c +++ b/xorg-server/glx/createcontext.c @@ -30,7 +30,8 @@ #include "indirect_dispatch.h" #define ALL_VALID_FLAGS \ - (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) + (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \ + | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) static Bool validate_GL_version(int major_version, int minor_version) @@ -90,6 +91,24 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) __GLXconfig *config; int err; + /* The GLX_ARB_create_context_robustness spec says: + * + * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB + * is GLX_NO_RESET_NOTIFICATION_ARB." + */ + int reset = GLX_NO_RESET_NOTIFICATION_ARB; + + /* The GLX_ARB_create_context_profile spec says: + * + * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is + * GLX_CONTEXT_CORE_PROFILE_BIT_ARB." + * + * The core profile only makes sense for OpenGL versions 3.2 and later. + * If the version ultimately specified is less than 3.2, the core profile + * bit is cleared (see below). + */ + int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + /* Verify that the size of the packet matches the size inferred from the * sizes specified for the various fields. */ @@ -161,6 +180,18 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) render_type = attribs[2 * i + 1]; break; + case GLX_CONTEXT_PROFILE_MASK_ARB: + profile = attribs[2 * i + 1]; + break; + + case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: + reset = attribs[2 * i + 1]; + if (reset != GLX_NO_RESET_NOTIFICATION_ARB + && reset != GLX_LOSE_CONTEXT_ON_RESET_ARB) + return BadValue; + + break; + default: return BadValue; } @@ -202,6 +233,73 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) if ((flags & ~ALL_VALID_FLAGS) != 0) return BadValue; + /* The GLX_ARB_create_context_profile spec says: + * + * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has + * any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and + * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of + * these bits set; or if the implementation does not support the + * requested profile, then GLXBadProfileARB is generated." + */ + switch (profile) { + case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: + case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: + break; + case GLX_CONTEXT_ES2_PROFILE_BIT_EXT: + /* The GLX_EXT_create_context_es2_profile spec says: + * + * "... If the version requested is 2.0, and the + * GLX_CONTEXT_ES2_PROFILE_BIT_EXT bit is set in the + * GLX_CONTEXT_PROFILE_MASK_ARB attribute (see below), then the + * context returned will implement OpenGL ES 2.0." + * + * It also says: + * + * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; + * has any bits set other than + * GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, or + * GLX_CONTEXT_ES2_PROFILE_BIT_EXT; has more than one of these + * bits set; or if the implementation does not supported the + * requested profile, then GLXBadProfileARB is generated." + * + * It does not specifically say what is supposed to happen if + * GLX_CONTEXT_ES2_PROFILE_BIT_EXT is set but the version requested is + * not 2.0. We choose to generate GLXBadProfileARB as this matches + * NVIDIA's behavior. + */ + if (major_version != 2 || minor_version != 0) + return __glXError(GLXBadProfileARB); + break; + default: + return __glXError(GLXBadProfileARB); + } + + /* The GLX_ARB_create_context_robustness spec says: + * + * "* If the reset notification behavior of <share_context> and the + * newly created context are different, BadMatch is generated." + */ + if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset) + return BadMatch; + + /* There is no GLX protocol for desktop OpenGL versions after 1.4. There + * is no GLX protocol for any version of OpenGL ES. If the application is + * requested an indirect rendering context for a version that cannot be + * satisfied, reject it. + * + * The GLX_ARB_create_context spec says: + * + * "* If <config> does not support compatible OpenGL contexts + * providing the requested API major and minor version, + * forward-compatible flag, and debug context flag, GLXBadFBConfig + * is generated." + */ + if (!req->isDirect && (major_version > 1 || minor_version > 4 + || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) { + return __glXError(GLXBadFBConfig); + } + /* Allocate memory for the new context */ if (req->isDirect) { @@ -232,6 +330,7 @@ __glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) ctx->selectBufSize = 0; ctx->drawPriv = NULL; ctx->readPriv = NULL; + ctx->resetNotificationStrategy = reset; /* Add the new context to the various global tables of GLX contexts. */ diff --git a/xorg-server/glx/extension_string.c b/xorg-server/glx/extension_string.c index 6a1a6c6b2..ee9864e64 100644 --- a/xorg-server/glx/extension_string.c +++ b/xorg-server/glx/extension_string.c @@ -70,8 +70,10 @@ static const struct extension_info known_glx_extensions[] = { /* *INDENT-OFF* */ { GLX(ARB_create_context), VER(0,0), N, }, { GLX(ARB_create_context_profile), VER(0,0), N, }, + { GLX(ARB_create_context_robustness), VER(0,0), N, }, { GLX(ARB_multisample), VER(1,4), Y, }, + { GLX(EXT_create_context_es2_profile), VER(0,0), N, }, { GLX(EXT_import_context), VER(0,0), Y, }, { GLX(EXT_texture_from_pixmap), VER(0,0), Y, }, { GLX(EXT_visual_info), VER(0,0), Y, }, diff --git a/xorg-server/glx/extension_string.h b/xorg-server/glx/extension_string.h index 947bf89e6..7a4a8b1c2 100644 --- a/xorg-server/glx/extension_string.h +++ b/xorg-server/glx/extension_string.h @@ -38,7 +38,9 @@ enum { /* GLX_ARB_get_proc_address is implemented on the client. */ ARB_create_context_bit = 0, ARB_create_context_profile_bit, + ARB_create_context_robustness_bit, ARB_multisample_bit, + EXT_create_context_es2_profile_bit, EXT_import_context_bit, EXT_texture_from_pixmap_bit, EXT_visual_info_bit, diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c index 265b8efa5..5e6e74f8b 100644 --- a/xorg-server/glx/glxcmds.c +++ b/xorg-server/glx/glxcmds.c @@ -318,6 +318,16 @@ DoCreateContext(__GLXclientState * cl, GLXContextID gcId, glxc->drawPriv = NULL; glxc->readPriv = NULL; + /* The GLX_ARB_create_context_robustness spec says: + * + * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB + * is GLX_NO_RESET_NOTIFICATION_ARB." + * + * Without using glXCreateContextAttribsARB, there is no way to specify a + * non-default reset notification strategy. + */ + glxc->resetNotificationStrategy = GLX_NO_RESET_NOTIFICATION_ARB; + /* Add the new context to the various global tables of GLX contexts. */ if (!__glXAddContext(glxc)) { diff --git a/xorg-server/glx/glxcontext.h b/xorg-server/glx/glxcontext.h index b803a7fd1..4764e56f5 100644 --- a/xorg-server/glx/glxcontext.h +++ b/xorg-server/glx/glxcontext.h @@ -104,6 +104,11 @@ struct __GLXcontext { */ GLenum renderMode; + /** + * Reset notification strategy used when a GPU reset occurs. + */ + GLenum resetNotificationStrategy; + /* ** Buffers for feedback and selection. */ diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c index 7b76c3a5f..1e99179d4 100644 --- a/xorg-server/glx/glxdri2.c +++ b/xorg-server/glx/glxdri2.c @@ -59,6 +59,16 @@ typedef struct __GLXDRIscreen __GLXDRIscreen; typedef struct __GLXDRIcontext __GLXDRIcontext; typedef struct __GLXDRIdrawable __GLXDRIdrawable; + +#ifdef __DRI2_ROBUSTNESS +#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \ + | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \ + | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS) +#else +#define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \ + | __DRI_CTX_FLAG_FORWARD_COMPATIBLE) +#endif + struct __GLXDRIscreen { __GLXscreen base; __DRIscreen *driScreen; @@ -381,7 +391,7 @@ __glXDRIscreenDestroy(__GLXscreen * baseScreen) static Bool dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, unsigned *major_ver, unsigned *minor_ver, - uint32_t *flags, unsigned *error) + uint32_t *flags, int *api, int *reset, unsigned *error) { unsigned i; @@ -395,6 +405,11 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, *major_ver = 1; *minor_ver = 0; +#ifdef __DRI2_ROBUSTNESS + *reset = __DRI_CTX_RESET_NO_NOTIFICATION; +#else + (void) reset; +#endif for (i = 0; i < num_attribs; i++) { switch (attribs[i * 2]) { @@ -409,6 +424,42 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, break; case GLX_RENDER_TYPE: break; + case GLX_CONTEXT_PROFILE_MASK_ARB: + switch (attribs[i * 2 + 1]) { + case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: + *api = __DRI_API_OPENGL_CORE; + break; + case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: + *api = __DRI_API_OPENGL; + break; + case GLX_CONTEXT_ES2_PROFILE_BIT_EXT: + *api = __DRI_API_GLES2; + break; + default: + *error = __glXError(GLXBadProfileARB); + return False; + } + break; +#ifdef __DRI2_ROBUSTNESS + case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: + if (screen->dri2->base.version >= 4) { + *error = BadValue; + return False; + } + + switch (attribs[i * 2 + 1]) { + case GLX_NO_RESET_NOTIFICATION_ARB: + *reset = __DRI_CTX_RESET_NO_NOTIFICATION; + break; + case GLX_LOSE_CONTEXT_ON_RESET_ARB: + *reset = __DRI_CTX_RESET_LOSE_CONTEXT; + break; + default: + *error = BadValue; + return False; + } + break; +#endif default: /* If an unknown attribute is received, fail. */ @@ -419,11 +470,21 @@ dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, /* Unknown flag value. */ - if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) { + if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) { *error = BadValue; return False; } + /* If the core profile is requested for a GL version is less than 3.2, + * request the non-core profile from the DRI driver. The core profile + * only makes sense for GL versions >= 3.2, and many DRI drivers that + * don't support OpenGL 3.2 may fail the request for a core profile. + */ + if (*api == __DRI_API_OPENGL_CORE + && (*major_ver < 3 || (*major_ver < 3 && *minor_ver < 2))) { + *api == __DRI_API_OPENGL; + } + *error = Success; return True; } @@ -447,11 +508,14 @@ create_driver_context(__GLXDRIcontext * context, unsigned major_ver; unsigned minor_ver; uint32_t flags; + int reset; + int api; if (num_attribs != 0) { if (!dri2_convert_glx_attribs(num_attribs, attribs, &major_ver, &minor_ver, - &flags, (unsigned *) error)) + &flags, &api, &reset, + (unsigned *) error)) return NULL; ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; @@ -467,11 +531,19 @@ create_driver_context(__GLXDRIcontext * context, */ ctx_attribs[num_ctx_attribs++] = flags; } + +#ifdef __DRI2_ROBUSTNESS + if (reset != __DRI_CTX_NO_RESET_NOTIFICATION) { + ctx_attribs[num_ctx_attribs++] = + __DRI_CTX_ATTRIB_RESET_NOTIFICATION; + ctx_attribs[num_ctx_attribs++] = reset; + } +#endif } context->driContext = (*screen->dri2->createContextAttribs)(screen->driScreen, - __DRI_API_OPENGL, + api, config->driConfig, driShare, num_ctx_attribs / 2, @@ -786,7 +858,14 @@ initializeExtensions(__GLXDRIscreen * screen) if (screen->dri2->base.version >= 3) { __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_create_context"); + __glXEnableExtension(screen->glx_enable_bits, + "GLX_ARB_create_context_profile"); + __glXEnableExtension(screen->glx_enable_bits, + "GLX_EXT_create_context_es2_profile"); LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context\n"); + LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context_profile\n"); + LogMessage(X_INFO, + "AIGLX: enabled GLX_EXT_create_context_es2_profile\n"); } #endif @@ -823,6 +902,16 @@ initializeExtensions(__GLXDRIscreen * screen) } #endif +#ifdef __DRI2_ROBUSTNESS + if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 && + screen->dri2->base.version >= 3) { + __glXEnableExtension(screen->glx_enable_bits, + "GLX_ARB_create_context_robustness"); + LogMessage(X_INFO, + "AIGLX: enabled GLX_ARB_create_context_robustness\n"); + } +#endif + /* Ignore unknown extensions */ } } diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h index 098130436..1b44c50bd 100644 --- a/xorg-server/glx/glxserver.h +++ b/xorg-server/glx/glxserver.h @@ -46,7 +46,6 @@ #include <resource.h> #include <scrnintstr.h> -#define GL_GLEXT_PROTOTYPES /* we want prototypes */ #include <GL/gl.h> #include <GL/glext.h> #include <GL/glxproto.h> diff --git a/xorg-server/hw/dmx/input/dmxevents.c b/xorg-server/hw/dmx/input/dmxevents.c index f73480824..28756203b 100644 --- a/xorg-server/hw/dmx/input/dmxevents.c +++ b/xorg-server/hw/dmx/input/dmxevents.c @@ -227,25 +227,25 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block) && pScreen->myNum == dmxScreen->index) { /* Screen is old screen */ if (block) - dmxSigioBlock(); + OsBlockSIGIO(); if (pDev) enqueueMotion(pDev, localX, localY); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); } else { /* Screen is new */ DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n", pScreen->myNum, dmxScreen->index, localX, localY); if (block) - dmxSigioBlock(); + OsBlockSIGIO(); mieqProcessInputEvents(); miPointerSetScreen(inputInfo.pointer, dmxScreen->index, localX, localY); if (pDev) enqueueMotion(pDev, localX, localY); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); } #if 00 miPointerGetPosition(inputInfo.pointer, &localX, &localY); @@ -387,12 +387,12 @@ dmxExtMotion(DMXLocalInputInfoPtr dmxLocal, } if (block) - dmxSigioBlock(); + OsBlockSIGIO(); valuator_mask_set_range(&mask, firstAxis, axesCount, v); QueuePointerEvents(pDevice, MotionNotify, 0, POINTER_ABSOLUTE, &mask); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); } static int @@ -492,10 +492,10 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); if (block) - dmxSigioBlock(); + OsBlockSIGIO(); QueueKeyboardEvents(pDevice, event, ke->keycode, &mask); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); break; case XI_DeviceButtonPress: case XI_DeviceButtonRelease: @@ -503,11 +503,11 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); if (block) - dmxSigioBlock(); + OsBlockSIGIO(); QueuePointerEvents(pDevice, event, ke->keycode, POINTER_ABSOLUTE, &mask); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); break; case XI_ProximityIn: case XI_ProximityOut: @@ -515,10 +515,10 @@ dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); if (block) - dmxSigioBlock(); + OsBlockSIGIO(); QueueProximityEvents(pDevice, event, &mask); if (block) - dmxSigioUnblock(); + OsReleaseSIGIO(); break; break; diff --git a/xorg-server/hw/dmx/input/dmxsigio.c b/xorg-server/hw/dmx/input/dmxsigio.c index 9b1b493b8..6ef543c8b 100644 --- a/xorg-server/hw/dmx/input/dmxsigio.c +++ b/xorg-server/hw/dmx/input/dmxsigio.c @@ -84,28 +84,6 @@ dmxSigioHandler(int sig) } } -/** Block SIGIO handling. */ -void -dmxSigioBlock(void) -{ - sigset_t s; - - sigemptyset(&s); - sigaddset(&s, SIGIO); - sigprocmask(SIG_BLOCK, &s, 0); -} - -/** Unblock SIGIO handling. */ -void -dmxSigioUnblock(void) -{ - sigset_t s; - - sigemptyset(&s); - sigaddset(&s, SIGIO); - sigprocmask(SIG_UNBLOCK, &s, 0); -} - static void dmxSigioHook(void) { diff --git a/xorg-server/hw/dmx/input/dmxsigio.h b/xorg-server/hw/dmx/input/dmxsigio.h index 4e4874929..9f30662d1 100644 --- a/xorg-server/hw/dmx/input/dmxsigio.h +++ b/xorg-server/hw/dmx/input/dmxsigio.h @@ -36,8 +36,6 @@ #ifndef _DMXSIGIO_H_ #define _DMXSIGIO_H_ -extern void dmxSigioBlock(void); -extern void dmxSigioUnblock(void); extern void dmxSigioEnableInput(void); extern void dmxSigioDisableInput(void); extern void dmxSigioRegister(DMXInputInfo * dmxInput, int fd); diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c index cfb1be811..f2363c15e 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr.c @@ -775,34 +775,14 @@ ephyrUpdateModifierState(unsigned int state) } } -static void -ephyrBlockSigio(void) -{ #ifdef _MSC_VER __asm int 3; #else - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_BLOCK, &set, 0); #endif -} - -static void -ephyrUnblockSigio(void) -{ #ifdef _MSC_VER __asm int 3; #else - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_UNBLOCK, &set, 0); #endif -} - static Bool ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) { @@ -819,11 +799,11 @@ int ephyrCurScreen; /*current event screen */ static void ephyrWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { - ephyrBlockSigio(); + OsBlockSIGIO(); ephyrCurScreen = pScreen->myNum; miPointerWarpCursor(inputInfo.pointer, pScreen, x, y); - ephyrUnblockSigio(); + OsReleaseSIGIO(); } miPointerScreenFuncRec ephyrPointerScreenFuncs = { diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index 9778d1fee..76424c1c5 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -102,34 +102,14 @@ KdSigio(int sig) (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); } -static void -KdBlockSigio(void) -{ #ifdef _MSC_VER __asm int 3; #else - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_BLOCK, &set, 0); #endif -} - -static void -KdUnblockSigio(void) -{ #ifdef _MSC_VER __asm int 3; #else - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_UNBLOCK, &set, 0); #endif -} - #ifdef DEBUG_SIGIO void @@ -281,7 +261,7 @@ KdDisableInput(void) KdPointerInfo *pi; int found = 0, i = 0; - KdBlockSigio(); + OsBlockSIGIO(); for (ki = kdKeyboards; ki; ki = ki->next) { if (ki->driver && ki->driver->Disable) @@ -363,7 +343,7 @@ KdEnableInput(void) NoticeEventTime(&ev, pi->dixdev); NoticeEventTime(&ev, ki->dixdev); - KdUnblockSigio(); + OsReleaseSIGIO(); } static KdKeyboardDriver * @@ -1824,7 +1804,7 @@ KdReleaseAllKeys(void) int key; KdKeyboardInfo *ki; - KdBlockSigio(); + OsBlockSIGIO(); for (ki = kdKeyboards; ki; ki = ki->next) { for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; key++) { @@ -1835,7 +1815,7 @@ KdReleaseAllKeys(void) } } - KdUnblockSigio(); + OsReleaseSIGIO(); #endif } @@ -2031,18 +2011,18 @@ KdWakeupHandler(ScreenPtr pScreen, unsigned long lresult, pointer readmask) if (kdInputEnabled && result > 0) { for (i = 0; i < kdNumInputFds; i++) if (FD_ISSET(kdInputFds[i].fd, pReadmask)) { - KdBlockSigio(); + OsBlockSIGIO(); (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); - KdUnblockSigio(); + OsReleaseSIGIO(); } } for (pi = kdPointers; pi; pi = pi->next) { if (pi->timeoutPending) { if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) { pi->timeoutPending = FALSE; - KdBlockSigio(); + OsBlockSIGIO(); KdReceiveTimeout(pi); - KdUnblockSigio(); + OsReleaseSIGIO(); } } } @@ -2139,10 +2119,10 @@ int KdCurScreen; /* current event screen */ static void KdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { - KdBlockSigio(); + OsBlockSIGIO(); KdCurScreen = pScreen->myNum; miPointerWarpCursor(pDev, pScreen, x, y); - KdUnblockSigio(); + OsReleaseSIGIO(); } miPointerScreenFuncRec kdPointerScreenFuncs = { diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c index b22b617a4..3ec40fe9b 100644 --- a/xorg-server/hw/xfree86/common/xf86Config.c +++ b/xorg-server/hw/xfree86/common/xf86Config.c @@ -2329,6 +2329,7 @@ checkInput(serverLayoutPtr layout, Bool implicit_layout) current = dev; free(*dev); + *dev = NULL; do { *current = *(current + 1); diff --git a/xorg-server/hw/xfree86/common/xf86Cursor.c b/xorg-server/hw/xfree86/common/xf86Cursor.c index c01cfd138..65a9e8264 100644 --- a/xorg-server/hw/xfree86/common/xf86Cursor.c +++ b/xorg-server/hw/xfree86/common/xf86Cursor.c @@ -199,7 +199,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) ScrnInfoPtr pScr = xf86ScreenToScrn(pScreen); ScreenPtr pCursorScreen; Bool Switched; - int px, py, was_blocked; + int px, py; DeviceIntPtr dev, it; if (!pScr->vtSema || !mode || !pScr->SwitchMode) @@ -228,7 +228,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) if (pScreen == pCursorScreen) miPointerGetPosition(dev, &px, &py); - was_blocked = xf86BlockSIGIO(); + OsBlockSIGIO(); Switched = (*pScr->SwitchMode) (pScr, mode); if (Switched) { pScr->currentMode = mode; @@ -267,7 +267,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) pScr->frameY1 = pScr->virtualY - 1; } } - xf86UnblockSIGIO(was_blocked); + OsReleaseSIGIO(); if (pScr->AdjustFrame) (*pScr->AdjustFrame) (pScr, pScr->frameX0, pScr->frameY0); @@ -469,13 +469,11 @@ xf86CrossScreen(ScreenPtr pScreen, Bool entering) static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { - int sigstate; - - sigstate = xf86BlockSIGIO(); + OsBlockSIGIO(); miPointerWarpCursor(pDev, pScreen, x, y); xf86Info.currentScreen = pScreen; - xf86UnblockSIGIO(sigstate); + OsReleaseSIGIO(); } void * diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index 4fcad4000..47429ecfe 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -254,7 +254,7 @@ xf86Wakeup(pointer blockData, int err, pointer pReadmask) while (pInfo) { if (pInfo->read_input && pInfo->fd >= 0 && (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) { - int sigstate = xf86BlockSIGIO(); + OsBlockSIGIO(); /* * Remove the descriptior from the set because more than one @@ -263,7 +263,7 @@ xf86Wakeup(pointer blockData, int err, pointer pReadmask) FD_CLR(pInfo->fd, &devicesWithInput); pInfo->read_input(pInfo); - xf86UnblockSIGIO(sigstate); + OsReleaseSIGIO(); } pInfo = pInfo->next; } @@ -397,9 +397,9 @@ xf86ReleaseKeys(DeviceIntPtr pDev) for (i = keyc->xkbInfo->desc->min_key_code; i < keyc->xkbInfo->desc->max_key_code; i++) { if (key_is_down(pDev, i, KEY_POSTED)) { - sigstate = xf86BlockSIGIO(); + OsBlockSIGIO(); QueueKeyboardEvents(pDev, KeyRelease, i, NULL); - xf86UnblockSIGIO(sigstate); + OsReleaseSIGIO(); } } } @@ -457,7 +457,7 @@ xf86VTSwitch(void) } } - prevSIGIO = xf86BlockSIGIO(); + OsBlockSIGIO(); for (i = 0; i < xf86NumScreens; i++) xf86Screens[i]->LeaveVT(xf86Screens[i]); @@ -492,7 +492,7 @@ xf86VTSwitch(void) for (ih = InputHandlers; ih; ih = ih->next) xf86EnableInputHandler(ih); - xf86UnblockSIGIO(prevSIGIO); + OsReleaseSIGIO(); } else { @@ -549,7 +549,7 @@ xf86VTSwitch(void) for (ih = InputHandlers; ih; ih = ih->next) xf86EnableInputHandler(ih); - xf86UnblockSIGIO(prevSIGIO); + OsReleaseSIGIO(); } } diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 84c866944..1f5a382b7 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -394,7 +394,7 @@ InstallSignalHandlers(void) void InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) { - int i, j, k, scr_index, was_blocked = 0; + int i, j, k, scr_index; char **modulelist; pointer *optionlist; Pix24Flags screenpix24, pix24; @@ -806,7 +806,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ); #endif xf86AccessEnter(); - was_blocked = xf86BlockSIGIO(); + OsBlockSIGIO(); } } @@ -879,7 +879,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) } xf86VGAarbiterWrapFunctions(); - xf86UnblockSIGIO(was_blocked); + OsReleaseSIGIO(); xf86InitOrigins(); @@ -964,6 +964,7 @@ OsVendorInit(void) } #endif #endif + OsReleaseSIGIO(); beenHere = TRUE; } @@ -1022,7 +1023,7 @@ AbortDDX(enum ExitCode error) { int i; - xf86BlockSIGIO(); + OsBlockSIGIO(); /* * try to restore the original video state diff --git a/xorg-server/hw/xfree86/common/xf86PM.c b/xorg-server/hw/xfree86/common/xf86PM.c index 1830640d5..15257cb81 100644 --- a/xorg-server/hw/xfree86/common/xf86PM.c +++ b/xorg-server/hw/xfree86/common/xf86PM.c @@ -92,8 +92,6 @@ eventName(pmEvent event, const char **str) } } -static int sigio_blocked_for_suspend; - static void suspend(pmEvent event, Bool undo) { @@ -109,7 +107,7 @@ suspend(pmEvent event, Bool undo) DisableDevice(pInfo->dev, TRUE); pInfo = pInfo->next; } - sigio_blocked_for_suspend = xf86BlockSIGIO(); + OsBlockSIGIO(); for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->PMEvent) xf86Screens[i]->PMEvent(xf86Screens[i], event, undo); @@ -137,7 +135,7 @@ resume(pmEvent event, Bool undo) xf86Screens[i]->EnterVT(xf86Screens[i]); } } - xf86UnblockSIGIO(sigio_blocked_for_suspend); + OsReleaseSIGIO(); for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->EnableDisableFBAccess) (*xf86Screens[i]->EnableDisableFBAccess) (xf86Screens[i], TRUE); @@ -153,7 +151,7 @@ resume(pmEvent event, Bool undo) static void DoApmEvent(pmEvent event, Bool undo) { - int i, was_blocked; + int i; switch (event) { #if 0 @@ -184,13 +182,13 @@ DoApmEvent(pmEvent event, Bool undo) } break; default: - was_blocked = xf86BlockSIGIO(); + OsBlockSIGIO(); for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->PMEvent) { xf86Screens[i]->PMEvent(xf86Screens[i], event, undo); } } - xf86UnblockSIGIO(was_blocked); + OsReleaseSIGIO(); break; } } diff --git a/xorg-server/hw/xfree86/loader/loader.c b/xorg-server/hw/xfree86/loader/loader.c index edaefb8f9..5fbea38f8 100644 --- a/xorg-server/hw/xfree86/loader/loader.c +++ b/xorg-server/hw/xfree86/loader/loader.c @@ -160,6 +160,12 @@ LoaderSymbol(const char *name) return NULL; } +void * +LoaderSymbolFromModule(void *handle, const char *name) +{ + return dlsym(handle, name); +} + void LoaderUnload(const char *name, void *handle) { diff --git a/xorg-server/hw/xfree86/loader/loader.h b/xorg-server/hw/xfree86/loader/loader.h index 5cadd5ad6..c89c6410a 100644 --- a/xorg-server/hw/xfree86/loader/loader.h +++ b/xorg-server/hw/xfree86/loader/loader.h @@ -72,5 +72,6 @@ extern unsigned long LoaderOptions; /* Internal Functions */ void *LoaderOpen(const char *, int *, int *); +void *LoaderSymbolFromModule(void *, const char *); #endif /* _LOADER_H */ diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c index 72020a58c..dd2057318 100644 --- a/xorg-server/hw/xfree86/loader/loadmod.c +++ b/xorg-server/hw/xfree86/loader/loadmod.c @@ -956,7 +956,7 @@ doLoadModule(const char *module, const char *path, const char **subdirlist, *errmin = 0; goto LoadModule_fail; } - initdata = LoaderSymbol(p); + initdata = LoaderSymbolFromModule(ret->handle, p); if (initdata) { ModuleSetupProc setup; ModuleTearDownProc teardown; diff --git a/xorg-server/hw/xfree86/os-support/shared/sigio.c b/xorg-server/hw/xfree86/os-support/shared/sigio.c index 231d6c04f..f3c153b89 100644 --- a/xorg-server/hw/xfree86/os-support/shared/sigio.c +++ b/xorg-server/hw/xfree86/os-support/shared/sigio.c @@ -136,7 +136,6 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure) struct sigaction sa; struct sigaction osa; int i; - int blocked; int installed = FALSE; if (!xf86Info.useSIGIO) @@ -146,7 +145,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure) if (!xf86SigIOFuncs[i].f) { if (xf86IsPipe(fd)) return 0; - blocked = xf86BlockSIGIO(); + OsBlockSIGIO(); #ifdef O_ASYNC if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC) == -1) { xf86Msg(X_WARNING, "fcntl(%d, O_ASYNC): %s\n", @@ -174,7 +173,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure) } #endif if (!installed) { - xf86UnblockSIGIO(blocked); + OsReleaseSIGIO(); return 0; } sigemptyset(&sa.sa_mask); @@ -190,7 +189,7 @@ xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure) if (fd >= xf86SigIOMaxFd) xf86SigIOMaxFd = fd + 1; FD_SET(fd, &xf86SigIOMask); - xf86UnblockSIGIO(blocked); + OsReleaseSIGIO(); return 1; } /* Allow overwriting of the closure and callback */ @@ -263,26 +262,13 @@ xf86RemoveSIGIOHandler(int fd) int xf86BlockSIGIO(void) { - sigset_t set, old; - int ret; - - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_BLOCK, &set, &old); - ret = sigismember(&old, SIGIO); - return ret; + return OsBlockSIGIO(); } void xf86UnblockSIGIO(int wasset) { - sigset_t set; - - if (!wasset) { - sigemptyset(&set); - sigaddset(&set, SIGIO); - sigprocmask(SIG_UNBLOCK, &set, NULL); - } + OsReleaseSIGIO(); } void diff --git a/xorg-server/include/list.h b/xorg-server/include/list.h index 96c0bcbd6..d54a207b1 100644 --- a/xorg-server/include/list.h +++ b/xorg-server/include/list.h @@ -453,7 +453,7 @@ xorg_list_is_empty(struct xorg_list *head) #define nt_list_del(_entry, _list, _type, _member) \ do { \ _type *__e = _entry; \ - if (__e == NULL) break; \ + if (__e == NULL || _list == NULL) break; \ if ((_list) == __e) { \ _list = __e->_member; \ } else { \ diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index cf487cbbe..3c272ae46 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -336,6 +336,12 @@ OsBlockSignals(void); extern _X_EXPORT void OsReleaseSignals(void); +extern _X_EXPORT int +OsBlockSIGIO(void); + +extern _X_EXPORT void +OsReleaseSIGIO(void); + extern _X_EXPORT void OsAbort(void) _X_NORETURN; diff --git a/xorg-server/include/privates.h b/xorg-server/include/privates.h index c34b9512c..2c8864b8a 100644 --- a/xorg-server/include/privates.h +++ b/xorg-server/include/privates.h @@ -33,9 +33,9 @@ typedef enum { PRIVATE_SCREEN, PRIVATE_EXTENSION, PRIVATE_COLORMAP, + PRIVATE_DEVICE, /* These cannot have any objects before all relevant keys are registered */ - PRIVATE_DEVICE, PRIVATE_CLIENT, PRIVATE_PROPERTY, PRIVATE_SELECTION, @@ -66,6 +66,13 @@ typedef struct _DevPrivateKeyRec { struct _DevPrivateKeyRec *next; } DevPrivateKeyRec, *DevPrivateKey; +typedef struct _DevPrivateSetRec { + DevPrivateKey key; + unsigned offset; + int created; + int allocated; +} DevPrivateSetRec, *DevPrivateSetPtr; + typedef struct _DevScreenPrivateKeyRec { DevPrivateKeyRec screenKey; } DevScreenPrivateKeyRec, *DevScreenPrivateKey; @@ -219,6 +226,51 @@ dixLookupScreenPrivateAddr(PrivatePtr *privates, const DevScreenPrivateKey key, } /* + * These functions relate to allocations related to a specific screen; + * space will only be available for objects allocated for use on that + * screen. As such, only objects which are related directly to a specific + * screen are candidates for allocation this way, this includes + * windows, pixmaps, gcs, pictures and colormaps. This key is + * used just like any other key using dixGetPrivate and friends. + * + * This is distinctly different from the ScreenPrivateKeys above which + * allocate space in global objects like cursor bits for a specific + * screen, allowing multiple screen-related chunks of storage in a + * single global object. + */ + +#define HAVE_SCREEN_SPECIFIC_PRIVATE_KEYS 1 + +extern _X_EXPORT Bool +dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, + DevPrivateType type, unsigned size); + +/* Clean up screen-specific privates before CloseScreen */ +extern void +dixFreeScreenSpecificPrivates(ScreenPtr pScreen); + +/* Initialize screen-specific privates in AddScreen */ +extern void +dixInitScreenSpecificPrivates(ScreenPtr pScreen); + +extern _X_EXPORT void * +_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen, + unsigned size, + unsigned clear, + unsigned offset, + DevPrivateType type); + +#define dixAllocateScreenObjectWithPrivates(s, t, type) _dixAllocateScreenObjectWithPrivates(s, sizeof(t), sizeof(t), offsetof(t, devPrivates), type) + +extern _X_EXPORT int +dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type); + +extern _X_EXPORT void +_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type); + +#define dixInitScreenPrivates(s, o, v, type) _dixInitScreenPrivates(s, &(o)->devPrivates, (v), type); + +/* * Allocates private data separately from main object. * * For objects created during server initialization, this allows those @@ -240,7 +292,7 @@ extern _X_EXPORT void * Initialize privates by zeroing them */ extern _X_EXPORT void - _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type); +_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type); #define dixInitPrivates(o, v, type) _dixInitPrivates(&(o)->devPrivates, (v), type); diff --git a/xorg-server/include/scrnintstr.h b/xorg-server/include/scrnintstr.h index a646d8854..746ff92e3 100644 --- a/xorg-server/include/scrnintstr.h +++ b/xorg-server/include/scrnintstr.h @@ -371,6 +371,8 @@ typedef struct _Screen { WindowPtr root; ScreenSaverStuffRec screensaver; + DevPrivateSetRec screenSpecificPrivates[PRIVATE_LAST]; + /* Random screen procedures */ CloseScreenProcPtr CloseScreen; diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index df141cdc7..edca9696f 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -56,9 +56,7 @@ in this Software without prior written authorization from The Open Group. static DevPrivateKeyRec miDCScreenKeyRec; #define miDCScreenKey (&miDCScreenKeyRec) -static DevScreenPrivateKeyRec miDCCursorBitsKeyRec; -#define miDCCursorBitsKey (&miDCCursorBitsKeyRec) static DevScreenPrivateKeyRec miDCDeviceKeyRec; #define miDCDeviceKey (&miDCDeviceKeyRec) @@ -86,18 +84,15 @@ typedef struct { */ typedef struct { CloseScreenProcPtr CloseScreen; -} miDCScreenRec, *miDCScreenPtr; - -#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey))) - -/* per-cursor per-screen private data */ -typedef struct { PixmapPtr sourceBits; /* source bits */ PixmapPtr maskBits; /* mask bits */ #ifdef ARGB_CURSOR PicturePtr pPicture; #endif -} miDCCursorRec, *miDCCursorPtr; + CursorPtr pCursor; +} miDCScreenRec, *miDCScreenPtr; + +#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey))) Bool miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) @@ -105,13 +100,11 @@ miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) miDCScreenPtr pScreenPriv; if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) || - !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, - PRIVATE_CURSOR_BITS, 0) || !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0)) return FALSE; - pScreenPriv = malloc(sizeof(miDCScreenRec)); + pScreenPriv = calloc(1, sizeof(miDCScreenRec)); if (!pScreenPriv) return FALSE; @@ -127,6 +120,28 @@ miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) return TRUE; } +static void +miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBits, PixmapPtr maskBits, PicturePtr pPicture) +{ + miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); + + if (pScreenPriv->sourceBits) + (*pScreen->DestroyPixmap)(pScreenPriv->sourceBits); + pScreenPriv->sourceBits = sourceBits; + + if (pScreenPriv->maskBits) + (*pScreen->DestroyPixmap)(pScreenPriv->maskBits); + pScreenPriv->maskBits = maskBits; + +#ifdef ARGB_CURSOR + if (pScreenPriv->pPicture) + FreePicture(pScreenPriv->pPicture, 0); + pScreenPriv->pPicture = pPicture; +#endif + + pScreenPriv->pCursor = pCursor; +} + static Bool miDCCloseScreen(ScreenPtr pScreen) { @@ -135,6 +150,8 @@ miDCCloseScreen(ScreenPtr pScreen) pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pScreen->CloseScreen = pScreenPriv->CloseScreen; + + miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL); free((pointer) pScreenPriv); return (*pScreen->CloseScreen) (pScreen); } @@ -142,9 +159,6 @@ miDCCloseScreen(ScreenPtr pScreen) Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) { - if (pCursor->bits->refcnt <= 1) - dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, - pScreen, NULL); return TRUE; } @@ -154,8 +168,6 @@ miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) static PicturePtr miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin) { - ScreenPtr pScreen = pDraw->pScreen; - VisualPtr pVisual; PictFormatPtr pFormat; XID subwindow_mode = IncludeInferiors; PicturePtr pPicture; @@ -172,42 +184,39 @@ miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin) } #endif -static miDCCursorPtr +static Bool miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) { - miDCCursorPtr pPriv; + miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); GCPtr pGC; ChangeGCVal gcvals; + PixmapPtr sourceBits, maskBits; + + if (pScreenPriv->pCursor == pCursor) + return TRUE; - pPriv = malloc(sizeof(miDCCursorRec)); - if (!pPriv) - return NULL; #ifdef ARGB_CURSOR + if (pCursor->bits->argb) { PixmapPtr pPixmap; PictFormatPtr pFormat; int error; + PicturePtr pPicture; pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8); - if (!pFormat) { - free((pointer) pPriv); - return NULL; - } + if (!pFormat) + return FALSE; - pPriv->sourceBits = 0; - pPriv->maskBits = 0; pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 32, CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) { - free((pointer) pPriv); - return NULL; - } + if (!pPixmap) + return FALSE; + pGC = GetScratchGC(32, pScreen); if (!pGC) { (*pScreen->DestroyPixmap) (pPixmap); - free((pointer) pPriv); - return NULL; + return FALSE; } ValidateGC(&pPixmap->drawable, pGC); (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, @@ -215,105 +224,86 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) pCursor->bits->height, 0, ZPixmap, (char *) pCursor->bits->argb); FreeScratchGC(pGC); - pPriv->pPicture = CreatePicture(0, &pPixmap->drawable, - pFormat, 0, 0, serverClient, &error); + pPicture = CreatePicture(0, &pPixmap->drawable, + pFormat, 0, 0, serverClient, &error); (*pScreen->DestroyPixmap) (pPixmap); - if (!pPriv->pPicture) { - free((pointer) pPriv); - return NULL; - } - dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, - pScreen, pPriv); - return pPriv; + if (!pPicture) + return FALSE; + + miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture); + return TRUE; } - pPriv->pPicture = 0; #endif - pPriv->sourceBits = - (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, - pCursor->bits->height, 1, 0); - if (!pPriv->sourceBits) { - free((pointer) pPriv); - return NULL; - } - pPriv->maskBits = - (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, - pCursor->bits->height, 1, 0); - if (!pPriv->maskBits) { - (*pScreen->DestroyPixmap) (pPriv->sourceBits); - free((pointer) pPriv); - return NULL; + sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, + pCursor->bits->height, 1, 0); + if (!sourceBits) + return FALSE; + + maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, + pCursor->bits->height, 1, 0); + if (!maskBits) { + (*pScreen->DestroyPixmap) (sourceBits); + return FALSE; } - dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, - pPriv); /* create the two sets of bits, clipping as appropriate */ pGC = GetScratchGC(1, pScreen); if (!pGC) { - (void) miDCUnrealizeCursor(pScreen, pCursor); - return NULL; + (*pScreen->DestroyPixmap) (sourceBits); + (*pScreen->DestroyPixmap) (maskBits); + return FALSE; } - ValidateGC((DrawablePtr) pPriv->sourceBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr) pPriv->sourceBits, pGC, 1, + ValidateGC((DrawablePtr) sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1, 0, 0, pCursor->bits->width, pCursor->bits->height, 0, XYPixmap, (char *) pCursor->bits->source); gcvals.val = GXand; ChangeGC(NullClient, pGC, GCFunction, &gcvals); - ValidateGC((DrawablePtr) pPriv->sourceBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr) pPriv->sourceBits, pGC, 1, + ValidateGC((DrawablePtr) sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1, 0, 0, pCursor->bits->width, pCursor->bits->height, 0, XYPixmap, (char *) pCursor->bits->mask); /* mask bits -- pCursor->mask & ~pCursor->source */ gcvals.val = GXcopy; ChangeGC(NullClient, pGC, GCFunction, &gcvals); - ValidateGC((DrawablePtr) pPriv->maskBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr) pPriv->maskBits, pGC, 1, + ValidateGC((DrawablePtr) maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1, 0, 0, pCursor->bits->width, pCursor->bits->height, 0, XYPixmap, (char *) pCursor->bits->mask); gcvals.val = GXandInverted; ChangeGC(NullClient, pGC, GCFunction, &gcvals); - ValidateGC((DrawablePtr) pPriv->maskBits, pGC); - (*pGC->ops->PutImage) ((DrawablePtr) pPriv->maskBits, pGC, 1, + ValidateGC((DrawablePtr) maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1, 0, 0, pCursor->bits->width, pCursor->bits->height, 0, XYPixmap, (char *) pCursor->bits->source); FreeScratchGC(pGC); - return pPriv; + + miDCSwitchScreenCursor(pScreen, pCursor, sourceBits, maskBits, NULL); + return TRUE; } Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) { - miDCCursorPtr pPriv; - - pPriv = (miDCCursorPtr) dixLookupScreenPrivate(&pCursor->bits->devPrivates, - miDCCursorBitsKey, pScreen); - if (pPriv && (pCursor->bits->refcnt <= 1)) { - if (pPriv->sourceBits) - (*pScreen->DestroyPixmap) (pPriv->sourceBits); - if (pPriv->maskBits) - (*pScreen->DestroyPixmap) (pPriv->maskBits); -#ifdef ARGB_CURSOR - if (pPriv->pPicture) - FreePicture(pPriv->pPicture, 0); -#endif - free((pointer) pPriv); - dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, - pScreen, NULL); - } + miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); + + if (pCursor == pScreenPriv->pCursor) + miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL); return TRUE; } static void miDCPutBits(DrawablePtr pDrawable, - miDCCursorPtr pPriv, GCPtr sourceGC, GCPtr maskGC, int x_org, int y_org, unsigned w, unsigned h, unsigned long source, unsigned long mask) { + miDCScreenPtr pScreenPriv = dixLookupPrivate(&pDrawable->pScreen->devPrivates, miDCScreenKey); ChangeGCVal gcval; int x, y; @@ -333,7 +323,7 @@ miDCPutBits(DrawablePtr pDrawable, y = y_org; } - (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, + (*sourceGC->ops->PushPixels) (sourceGC, pScreenPriv->sourceBits, pDrawable, w, h, x, y); if (maskGC->fgPixel != mask) { gcval.val = mask; @@ -351,7 +341,7 @@ miDCPutBits(DrawablePtr pDrawable, y = y_org; } - (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); + (*maskGC->ops->PushPixels) (maskGC, pScreenPriv->maskBits, pDrawable, w, h, x, y); } static GCPtr @@ -373,27 +363,22 @@ Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y, unsigned long source, unsigned long mask) { - miDCCursorPtr pPriv; + miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); miDCBufferPtr pBuffer; WindowPtr pWin; - pPriv = (miDCCursorPtr) dixLookupScreenPrivate(&pCursor->bits->devPrivates, - miDCCursorBitsKey, pScreen); - if (!pPriv) { - pPriv = miDCRealize(pScreen, pCursor); - if (!pPriv) - return FALSE; - } + if (!miDCRealize(pScreen, pCursor)) + return FALSE; pWin = pScreen->root; pBuffer = miGetDCDevice(pDev, pScreen); #ifdef ARGB_CURSOR - if (pPriv->pPicture) { + if (pScreenPriv->pPicture) { if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) return FALSE; CompositePicture(PictOpOver, - pPriv->pPicture, + pScreenPriv->pPicture, NULL, pBuffer->pRootPicture, 0, 0, 0, 0, @@ -402,7 +387,7 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, else #endif { - miDCPutBits((DrawablePtr) pWin, pPriv, + miDCPutBits((DrawablePtr) pWin, pBuffer->pSourceGC, pBuffer->pMaskGC, x, y, pCursor->bits->width, pCursor->bits->height, source, mask); diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index e94179518..d61a9d67d 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -1226,15 +1226,15 @@ OsBlockSignals(void) if (BlockedSignalCount++ == 0) { sigset_t set; +#ifdef SIGIO + OsBlockSIGIO(); +#endif sigemptyset(&set); sigaddset(&set, SIGALRM); sigaddset(&set, SIGVTALRM); #ifdef SIGWINCH sigaddset(&set, SIGWINCH); #endif -#ifdef SIGIO - sigaddset(&set, SIGIO); -#endif sigaddset(&set, SIGTSTP); sigaddset(&set, SIGTTIN); sigaddset(&set, SIGTTOU); @@ -1244,12 +1244,60 @@ OsBlockSignals(void) #endif } +#ifdef SIG_BLOCK +static sig_atomic_t sigio_blocked; +#endif + +/** + * returns zero if this call caused SIGIO to be blocked now, non-zero if it + * was already blocked by a previous call to this function. + */ +int +OsBlockSIGIO(void) +{ +#ifdef SIGIO +#ifdef SIG_BLOCK + if (sigio_blocked++ == 0) { + sigset_t set, old; + int ret; + + sigemptyset(&set); + sigaddset(&set, SIGIO); + sigprocmask(SIG_BLOCK, &set, &old); + ret = sigismember(&old, SIGIO); + return ret; + } else + return 1; +#endif +#endif +} + +void +OsReleaseSIGIO(void) +{ +#ifdef SIGIO +#ifdef SIG_BLOCK + if (--sigio_blocked == 0) { + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGIO); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } else if (sigio_blocked < 0) { + BUG_WARN(sigio_blocked < 0); + sigio_blocked = 0; + } +#endif +#endif +} + void OsReleaseSignals(void) { #ifdef SIG_BLOCK if (--BlockedSignalCount == 0) { sigprocmask(SIG_SETMASK, &PreviousSignalMask, 0); + OsReleaseSIGIO(); } #endif } diff --git a/xorg-server/render/picture.c b/xorg-server/render/picture.c index ebbfa29e9..2908b7629 100644 --- a/xorg-server/render/picture.c +++ b/xorg-server/render/picture.c @@ -763,7 +763,8 @@ CreatePicture(Picture pid, PicturePtr pPicture; PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen); - pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); + pPicture = dixAllocateScreenObjectWithPrivates(pDrawable->pScreen, + PictureRec, PRIVATE_PICTURE); if (!pPicture) { *error = BadAlloc; return 0; @@ -853,7 +854,7 @@ createSourcePicture(void) { PicturePtr pPicture; - pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE); + pPicture = dixAllocateScreenObjectWithPrivates(NULL, PictureRec, PRIVATE_PICTURE); pPicture->pDrawable = 0; pPicture->pFormat = 0; pPicture->pNext = 0; diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index e5b25c97f..15c51ed22 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -5,7 +5,7 @@ if XORG # Tests that require at least some DDX functions in order to fully link # For now, requires xf86 ddx, could be adjusted to use another SUBDIRS += xi2 -noinst_PROGRAMS += xkb input xtest misc fixes xfree86 hashtabletest signal-logging +noinst_PROGRAMS += xkb input xtest misc fixes xfree86 hashtabletest os signal-logging endif check_LTLIBRARIES = libxservertest.la @@ -38,6 +38,7 @@ xfree86_LDADD=$(TEST_LDADD) touch_LDADD=$(TEST_LDADD) signal_logging_LDADD=$(TEST_LDADD) hashtabletest_LDADD=$(TEST_LDADD) $(top_srcdir)/Xext/hashtable.c +os_LDADD=$(TEST_LDADD) libxservertest_la_LIBADD = $(XSERVER_LIBS) if XORG diff --git a/xorg-server/test/os.c b/xorg-server/test/os.c new file mode 100644 index 000000000..1460a34d6 --- /dev/null +++ b/xorg-server/test/os.c @@ -0,0 +1,130 @@ +/** + * Copyright © 2012 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <signal.h> +#include "os.h" + +static int +sig_is_blocked(int sig) +{ + sigset_t current; + + sigemptyset(¤t); + assert(sigprocmask(SIG_BLOCK, NULL, ¤t) == 0); + return sigismember(¤t, sig); +} + +static void block_sigio_test(void) +{ +#ifdef SIG_BLOCK + sigset_t current; + + sigemptyset(¤t); + assert(!sig_is_blocked(SIGIO)); + + /* block once */ + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(!sig_is_blocked(SIGIO)); + + /* block twice, nested */ + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(!sig_is_blocked(SIGIO)); + + /* block all */ + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(!sig_is_blocked(SIGIO)); + + /* block all nested */ + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(!sig_is_blocked(SIGIO)); + + /* mix the two */ + /* ABBA */ + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(!sig_is_blocked(SIGIO)); + + /* ABAB */ + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(!sig_is_blocked(SIGIO)); + + /* BAAB */ + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(!sig_is_blocked(SIGIO)); + + /* BABA */ + OsBlockSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsBlockSignals(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSIGIO(); + assert(sig_is_blocked(SIGIO)); + OsReleaseSignals(); + assert(!sig_is_blocked(SIGIO)); + +#endif +} + +int +main(int argc, char **argv) +{ + block_sigio_test(); + return 0; +} diff --git a/xorg-server/xkb/xkbAccessX.c b/xorg-server/xkb/xkbAccessX.c index fe28e12d7..082c0db57 100644 --- a/xorg-server/xkb/xkbAccessX.c +++ b/xorg-server/xkb/xkbAccessX.c @@ -281,12 +281,12 @@ AccessXStickyKeysTurnOff(DeviceIntPtr dev, xkbControlsNotify * pCN) static CARD32 AccessXKRGExpire(OsTimerPtr timer, CARD32 now, pointer arg) { - XkbSrvInfoPtr xkbi = ((DeviceIntPtr) arg)->key->xkbInfo; xkbControlsNotify cn; + DeviceIntPtr dev = arg; + XkbSrvInfoPtr xkbi = dev->key->xkbInfo; if (xkbi->krgTimerActive == _KRG_WARN_TIMER) { - XkbDDXAccessXBeep((DeviceIntPtr) arg, _BEEP_SLOW_WARN, - XkbStickyKeysMask); + XkbDDXAccessXBeep(dev, _BEEP_SLOW_WARN, XkbStickyKeysMask); xkbi->krgTimerActive = _KRG_TIMER; return 4000; } @@ -296,11 +296,11 @@ AccessXKRGExpire(OsTimerPtr timer, CARD32 now, pointer arg) cn.requestMajor = 0; cn.requestMinor = 0; if (xkbi->desc->ctrls->enabled_ctrls & XkbSlowKeysMask) { - AccessXKRGTurnOff((DeviceIntPtr) arg, &cn); + AccessXKRGTurnOff(dev, &cn); LogMessage(X_INFO, "XKB SlowKeys are disabled.\n"); } else { - AccessXKRGTurnOn((DeviceIntPtr) arg, XkbSlowKeysMask, &cn); + AccessXKRGTurnOn(dev, XkbSlowKeysMask, &cn); LogMessage(X_INFO, "XKB SlowKeys are now enabled. Hold shift to disable.\n"); } |