devPrivates rework: add new interface implementation.
This commit is contained in:
parent
779faccfb7
commit
16f2b8892d
317
dix/privates.c
317
dix/privates.c
|
@ -36,6 +36,7 @@ from The Open Group.
|
|||
#include "os.h"
|
||||
#include "windowstr.h"
|
||||
#include "resource.h"
|
||||
#include "privates.h"
|
||||
#include "dixstruct.h"
|
||||
#include "gcstruct.h"
|
||||
#include "colormapst.h"
|
||||
|
@ -44,6 +45,322 @@ from The Open Group.
|
|||
#include "inputstr.h"
|
||||
#include "extnsionst.h"
|
||||
|
||||
typedef struct _PrivateDescItem {
|
||||
int index;
|
||||
RESTYPE type;
|
||||
pointer parent;
|
||||
unsigned size;
|
||||
CallbackListPtr initfuncs;
|
||||
CallbackListPtr deletefuncs;
|
||||
} PrivateDescItemRec, *PrivateDescItemPtr;
|
||||
|
||||
/* keeps track of whether resource objects have been created */
|
||||
static char *instances = NULL;
|
||||
static RESTYPE instancesSize = 0;
|
||||
static char anyInstances = 0;
|
||||
|
||||
/* list of all allocated privates */
|
||||
static PrivateDescItemPtr items = NULL;
|
||||
static unsigned itemsSize = 0;
|
||||
static unsigned nextPrivateIndex = 0;
|
||||
|
||||
/* number of extra slots to add when resizing the tables */
|
||||
#define PRIV_TAB_INCREMENT 48
|
||||
/* set in index value for privates registered after resources were created */
|
||||
#define PRIV_DYN_MASK (1<<30)
|
||||
/* descriptor item lookup convenience macro */
|
||||
#define GET_DESCRIPTOR(index) (items + ((index) & (PRIV_DYN_MASK - 1)))
|
||||
/* type mask convenience macro */
|
||||
#define TYPE_BITS(type) ((type) & TypeMask)
|
||||
|
||||
static _X_INLINE ResourcePtr
|
||||
findResourceBucket(RESTYPE type, pointer instance) {
|
||||
ResourcePtr res = *((ResourcePtr *)instance);
|
||||
|
||||
while (res->type != type)
|
||||
res = res->nexttype;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Request functions; the latter calls the former internally.
|
||||
*/
|
||||
_X_EXPORT int
|
||||
dixRequestPrivate(RESTYPE type, unsigned size, pointer parent)
|
||||
{
|
||||
int index = nextPrivateIndex;
|
||||
|
||||
/* check if privates descriptor table needs to be resized */
|
||||
if (nextPrivateIndex >= itemsSize) {
|
||||
unsigned bytes;
|
||||
unsigned size = itemsSize;
|
||||
|
||||
while (nextPrivateIndex >= size)
|
||||
size += PRIV_TAB_INCREMENT;
|
||||
|
||||
bytes = size * sizeof(PrivateDescItemRec);
|
||||
items = (PrivateDescItemPtr)xrealloc(items, bytes);
|
||||
if (!items) {
|
||||
itemsSize = nextPrivateIndex = 0;
|
||||
return -1;
|
||||
}
|
||||
memset(items + itemsSize, 0,
|
||||
(size - itemsSize) * sizeof(PrivateDescItemRec));
|
||||
}
|
||||
|
||||
/* figure out if resource instances already exist */
|
||||
if ((type != RC_ANY && instances[TYPE_BITS(type)]) ||
|
||||
(type == RC_ANY && anyInstances))
|
||||
index |= PRIV_DYN_MASK;
|
||||
|
||||
/* add privates descriptor */
|
||||
items[nextPrivateIndex].index = index;
|
||||
items[nextPrivateIndex].type = type;
|
||||
items[nextPrivateIndex].parent = parent;
|
||||
items[nextPrivateIndex].size = size;
|
||||
nextPrivateIndex++;
|
||||
return index;
|
||||
}
|
||||
|
||||
_X_EXPORT int
|
||||
dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance)
|
||||
{
|
||||
PrivatePtr ptr;
|
||||
ResourcePtr res = findResourceBucket(type, instance);
|
||||
int index = dixRequestPrivate(type, size, instance);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + size);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
ptr->index = index;
|
||||
ptr->value = ptr + 1;
|
||||
ptr->next = res->privates;
|
||||
res->privates = ptr;
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup function (some of this could be static inlined)
|
||||
*/
|
||||
_X_EXPORT pointer
|
||||
dixLookupPrivate(RESTYPE type, int index, pointer instance)
|
||||
{
|
||||
ResourcePtr res = findResourceBucket(type, instance);
|
||||
PrivatePtr ptr = res->privates;
|
||||
PrivateDescItemPtr item;
|
||||
PrivateCallbackRec calldata;
|
||||
|
||||
/* see if private has already been allocated (likely) */
|
||||
while (ptr) {
|
||||
if (ptr->index == index)
|
||||
return ptr->value;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
/* past this point, need to create private on the fly */
|
||||
/* create the new private */
|
||||
item = GET_DESCRIPTOR(index);
|
||||
ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + item->size);
|
||||
if (!ptr)
|
||||
return NULL;
|
||||
memset(ptr, 0, sizeof(PrivateRec) + item->size);
|
||||
ptr->index = index;
|
||||
ptr->value = ptr + 1;
|
||||
ptr->next = res->privates;
|
||||
res->privates = ptr;
|
||||
|
||||
/* call any init funcs and return */
|
||||
calldata.value = ptr->value;
|
||||
calldata.index = index;
|
||||
calldata.resource = res;
|
||||
CallCallbacks(&item->initfuncs, &calldata);
|
||||
return ptr->value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback registration
|
||||
*/
|
||||
_X_EXPORT int
|
||||
dixRegisterPrivateInitFunc(RESTYPE type, int index,
|
||||
CallbackProcPtr callback, pointer data)
|
||||
{
|
||||
return AddCallback(&GET_DESCRIPTOR(index)->initfuncs, callback, data);
|
||||
}
|
||||
|
||||
_X_EXPORT int
|
||||
dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
|
||||
CallbackProcPtr callback, pointer data)
|
||||
{
|
||||
return AddCallback(&GET_DESCRIPTOR(index)->deletefuncs, callback, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function called from the main loop to reset the subsystem.
|
||||
*/
|
||||
void
|
||||
dixResetPrivates(void)
|
||||
{
|
||||
if (items)
|
||||
xfree(items);
|
||||
items = NULL;
|
||||
itemsSize = 0;
|
||||
nextPrivateIndex = 0;
|
||||
|
||||
if (instances)
|
||||
xfree(instances);
|
||||
instances = NULL;
|
||||
instancesSize = 0;
|
||||
anyInstances = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function called from CreateNewResourceType.
|
||||
*/
|
||||
int
|
||||
dixUpdatePrivates(void)
|
||||
{
|
||||
RESTYPE next = lastResourceType + 1;
|
||||
|
||||
/* check if instances table needs to be resized */
|
||||
if (next >= instancesSize) {
|
||||
RESTYPE size = instancesSize;
|
||||
|
||||
while (next >= size)
|
||||
size += PRIV_TAB_INCREMENT;
|
||||
|
||||
instances = (char *)xrealloc(instances, size);
|
||||
if (!instances) {
|
||||
instancesSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
memset(instances + instancesSize, 0, size - instancesSize);
|
||||
instancesSize = size;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function called from dixAddResource.
|
||||
* Allocates a ResourceRec along with any private space all in one chunk.
|
||||
*/
|
||||
ResourcePtr
|
||||
dixAllocateResourceRec(RESTYPE type, pointer instance, pointer parent)
|
||||
{
|
||||
unsigned i, count = 0, size = sizeof(ResourceRec);
|
||||
ResourcePtr res;
|
||||
PrivatePtr ptr;
|
||||
char *value;
|
||||
|
||||
/* first pass figures out total size */
|
||||
for (i=0; i<nextPrivateIndex; i++)
|
||||
if (items[i].type == type &&
|
||||
(items[i].parent == NULL || items[i].parent == parent)) {
|
||||
|
||||
size += sizeof(PrivateRec) + items[i].size;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* allocate resource bucket */
|
||||
res = (ResourcePtr)xalloc(size);
|
||||
if (!res)
|
||||
return res;
|
||||
memset(res, 0, size);
|
||||
ptr = (PrivatePtr)(res + 1);
|
||||
value = (char *)(ptr + count);
|
||||
res->privates = (count > 0) ? ptr : NULL;
|
||||
|
||||
/* second pass sets up privates records */
|
||||
count = 0;
|
||||
for (i=0; i<nextPrivateIndex; i++)
|
||||
if (items[i].type == type &&
|
||||
(items[i].parent == NULL || items[i].parent == parent)) {
|
||||
|
||||
ptr[count].index = items[i].index;
|
||||
ptr[count].value = value;
|
||||
ptr[count].next = ptr + (count + 1);
|
||||
count++;
|
||||
value += items[i].size;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
ptr[count-1].next = NULL;
|
||||
|
||||
/* hook up back-pointer to resource record(s) */
|
||||
if (type & RC_PRIVATES) {
|
||||
res->nexttype = *((ResourcePtr *)instance);
|
||||
*((ResourcePtr *)instance) = res;
|
||||
}
|
||||
|
||||
instances[TYPE_BITS(type)] = anyInstances = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function called from dixAddResource.
|
||||
* Calls the init functions on a newly allocated resource.
|
||||
*/
|
||||
void
|
||||
dixCallPrivateInitFuncs(ResourcePtr res)
|
||||
{
|
||||
PrivatePtr ptr = res->privates;
|
||||
PrivateCallbackRec calldata;
|
||||
|
||||
calldata.resource = res;
|
||||
while (ptr) {
|
||||
calldata.value = ptr->value;
|
||||
calldata.index = ptr->index;
|
||||
CallCallbacks(&GET_DESCRIPTOR(ptr->index)->initfuncs, &calldata);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function called from the various delete resource functions.
|
||||
* Calls delete callbacks before freeing the ResourceRec and other bits.
|
||||
*/
|
||||
void
|
||||
dixFreeResourceRec(ResourcePtr res)
|
||||
{
|
||||
ResourcePtr *tmp;
|
||||
PrivatePtr ptr, next, base;
|
||||
PrivateCallbackRec calldata;
|
||||
|
||||
/* first pass calls the delete callbacks */
|
||||
ptr = res->privates;
|
||||
calldata.resource = res;
|
||||
while (ptr) {
|
||||
calldata.value = ptr->value;
|
||||
calldata.index = ptr->index;
|
||||
CallCallbacks(&GET_DESCRIPTOR(ptr->index)->deletefuncs, &calldata);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
/* second pass frees any off-struct private records */
|
||||
ptr = res->privates;
|
||||
base = (PrivatePtr)(res + 1);
|
||||
while (ptr && ptr != base) {
|
||||
next = ptr->next;
|
||||
xfree(ptr);
|
||||
ptr = next;
|
||||
}
|
||||
|
||||
/* remove the record from the nexttype linked list and free it*/
|
||||
if (res->type & RC_PRIVATES) {
|
||||
tmp = (ResourcePtr *)res->value;
|
||||
while (*tmp != res)
|
||||
tmp = &(*tmp)->nexttype;
|
||||
*tmp = (*tmp)->nexttype;
|
||||
}
|
||||
xfree(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Following is the old devPrivates support. These functions and variables
|
||||
* are deprecated, and should no longer be used.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See the Wrappers and devPrivates section in "Definition of the
|
||||
* Porting Layer for the X v11 Sample Server" (doc/Server/ddx.tbl.ms)
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "globals.h"
|
||||
#include "os.h"
|
||||
#include "osdep.h"
|
||||
#include "privates.h"
|
||||
#include "resource.h"
|
||||
#include "servermd.h"
|
||||
#include "scrnintstr.h"
|
||||
|
@ -259,6 +260,11 @@ _X_HIDDEN void *dixLookupTab[] = {
|
|||
SYMFUNC(GetScratchPixmapHeader)
|
||||
SYMFUNC(FreeScratchPixmapHeader)
|
||||
/* privates.c */
|
||||
SYMFUNC(dixRequestPrivate)
|
||||
SYMFUNC(dixRequestSinglePrivate)
|
||||
SYMFUNC(dixLookupPrivate)
|
||||
SYMFUNC(dixRegisterPrivateInitFunc)
|
||||
SYMFUNC(dixRegisterPrivateDeleteFunc)
|
||||
SYMFUNC(AllocateExtensionPrivate)
|
||||
SYMFUNC(AllocateExtensionPrivateIndex)
|
||||
SYMFUNC(AllocateClientPrivate)
|
||||
|
|
Loading…
Reference in New Issue
Block a user