devPrivates rework: redo interface and implementation.
This commit is contained in:
parent
74f1de1de9
commit
e684824709
|
@ -357,7 +357,8 @@ main(int argc, char *argv[], char *envp[])
|
||||||
InitAtoms();
|
InitAtoms();
|
||||||
InitEvents();
|
InitEvents();
|
||||||
InitGlyphCaching();
|
InitGlyphCaching();
|
||||||
dixResetPrivates();
|
if (!dixResetPrivates())
|
||||||
|
FatalError("couldn't init private data storage");
|
||||||
ResetExtensionPrivates();
|
ResetExtensionPrivates();
|
||||||
ResetClientPrivates();
|
ResetClientPrivates();
|
||||||
ResetScreenPrivates();
|
ResetScreenPrivates();
|
||||||
|
|
437
dix/privates.c
437
dix/privates.c
|
@ -31,6 +31,7 @@ from The Open Group.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "scrnintstr.h"
|
#include "scrnintstr.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
@ -45,315 +46,265 @@ from The Open Group.
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
#include "extnsionst.h"
|
#include "extnsionst.h"
|
||||||
|
|
||||||
typedef struct _PrivateDescItem {
|
typedef struct _PrivateDesc {
|
||||||
int index;
|
devprivate_key_t *key;
|
||||||
RESTYPE type;
|
RESTYPE type;
|
||||||
pointer parent;
|
pointer parent;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
CallbackListPtr initfuncs;
|
CallbackListPtr initfuncs;
|
||||||
CallbackListPtr deletefuncs;
|
CallbackListPtr deletefuncs;
|
||||||
} PrivateDescItemRec, *PrivateDescItemPtr;
|
struct _PrivateDesc *next;
|
||||||
|
} PrivateDescRec;
|
||||||
/* 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 */
|
/* list of all allocated privates */
|
||||||
static PrivateDescItemPtr items = NULL;
|
static PrivateDescRec *items = NULL;
|
||||||
static unsigned itemsSize = 0;
|
|
||||||
static unsigned nextPrivateIndex = 0;
|
|
||||||
|
|
||||||
/* number of extra slots to add when resizing the tables */
|
static _X_INLINE PrivateDescRec *
|
||||||
#define PRIV_TAB_INCREMENT 48
|
findItem(devprivate_key_t *const key)
|
||||||
/* set in index value for privates registered after resources were created */
|
{
|
||||||
#define PRIV_DYN_MASK (1<<30)
|
PrivateDescRec *item = items;
|
||||||
/* descriptor item lookup convenience macro */
|
while (item) {
|
||||||
#define GET_DESCRIPTOR(index) (items + ((index) & (PRIV_DYN_MASK - 1)))
|
if (item->key == key)
|
||||||
/* type mask convenience macro */
|
return item;
|
||||||
#define TYPE_BITS(type) ((type) & TypeMask)
|
item = item->next;
|
||||||
|
}
|
||||||
static _X_INLINE ResourcePtr
|
return NULL;
|
||||||
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.
|
* Request pre-allocated space in resources of a given type.
|
||||||
*/
|
*/
|
||||||
_X_EXPORT int
|
_X_EXPORT int
|
||||||
dixRequestPrivate(RESTYPE type, unsigned size, pointer parent)
|
dixRequestPrivate(RESTYPE type, devprivate_key_t *const key,
|
||||||
|
unsigned size, pointer parent)
|
||||||
{
|
{
|
||||||
int index = nextPrivateIndex;
|
PrivateDescRec *item = findItem(key);
|
||||||
|
if (item) {
|
||||||
/* check if privates descriptor table needs to be resized */
|
assert(item->type == type);
|
||||||
if (nextPrivateIndex >= itemsSize) {
|
if (size > item->size)
|
||||||
unsigned bytes;
|
item->size = size;
|
||||||
unsigned size = itemsSize;
|
} else {
|
||||||
|
item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec));
|
||||||
while (nextPrivateIndex >= size)
|
if (!item)
|
||||||
size += PRIV_TAB_INCREMENT;
|
return FALSE;
|
||||||
|
memset(item, 0, sizeof(PrivateDescRec));
|
||||||
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 */
|
/* add privates descriptor */
|
||||||
items[nextPrivateIndex].index = index;
|
item->key = key;
|
||||||
items[nextPrivateIndex].type = type;
|
item->type = type;
|
||||||
items[nextPrivateIndex].parent = parent;
|
item->parent = parent;
|
||||||
items[nextPrivateIndex].size = size;
|
item->size = size;
|
||||||
nextPrivateIndex++;
|
item->next = items;
|
||||||
return index;
|
items = item;
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
_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)
|
* Allocate a private and attach it to an existing object.
|
||||||
*/
|
*/
|
||||||
_X_EXPORT pointer
|
_X_EXPORT pointer *
|
||||||
dixLookupPrivate(RESTYPE type, int index, pointer instance)
|
dixAllocatePrivate(PrivateRec **privates, devprivate_key_t *const key)
|
||||||
{
|
{
|
||||||
ResourcePtr res = findResourceBucket(type, instance);
|
PrivateDescRec *item = findItem(key);
|
||||||
PrivatePtr ptr = res->privates;
|
PrivateRec *ptr;
|
||||||
PrivateDescItemPtr item;
|
unsigned size = sizeof(PrivateRec);
|
||||||
PrivateCallbackRec calldata;
|
|
||||||
|
|
||||||
/* see if private has already been allocated (likely) */
|
if (item)
|
||||||
while (ptr) {
|
size += item->size;
|
||||||
if (ptr->index == index)
|
|
||||||
return ptr->value;
|
|
||||||
ptr = ptr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* past this point, need to create private on the fly */
|
ptr = (PrivateRec *)xalloc(size);
|
||||||
/* create the new private */
|
|
||||||
item = GET_DESCRIPTOR(index);
|
|
||||||
ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + item->size);
|
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset(ptr, 0, sizeof(PrivateRec) + item->size);
|
memset(ptr, 0, size);
|
||||||
ptr->index = index;
|
ptr->key = key;
|
||||||
ptr->value = ptr + 1;
|
ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL;
|
||||||
ptr->next = res->privates;
|
ptr->next = *privates;
|
||||||
res->privates = ptr;
|
*privates = ptr;
|
||||||
|
|
||||||
/* call any init funcs and return */
|
/* call any init funcs and return */
|
||||||
calldata.value = ptr->value;
|
if (item) {
|
||||||
calldata.index = index;
|
PrivateCallbackRec calldata = { key, ptr->value };
|
||||||
calldata.resource = res;
|
|
||||||
CallCallbacks(&item->initfuncs, &calldata);
|
CallCallbacks(&item->initfuncs, &calldata);
|
||||||
return ptr->value;
|
}
|
||||||
|
return &ptr->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates pre-requested privates in a single chunk.
|
||||||
|
*/
|
||||||
|
_X_EXPORT PrivateRec *
|
||||||
|
dixAllocatePrivates(RESTYPE type, pointer parent)
|
||||||
|
{
|
||||||
|
unsigned count = 0, size = 0;
|
||||||
|
PrivateCallbackRec calldata;
|
||||||
|
PrivateDescRec *item;
|
||||||
|
PrivateRec *ptr;
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
/* first pass figures out total size */
|
||||||
|
for (item = items; item; item = item->next)
|
||||||
|
if ((item->type == type || item->type == RC_ANY) &&
|
||||||
|
(item->parent == NULL || item->parent == parent)) {
|
||||||
|
|
||||||
|
size += sizeof(PrivateRec) + item->size;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate one chunk of memory for everything */
|
||||||
|
ptr = (PrivateRec *)xalloc(size);
|
||||||
|
if (!ptr)
|
||||||
|
return NULL;
|
||||||
|
memset(ptr, 0, size);
|
||||||
|
value = (char *)(ptr + count);
|
||||||
|
|
||||||
|
/* second pass sets up records and calls init funcs */
|
||||||
|
count = 0;
|
||||||
|
for (item = items; item; item = item->next)
|
||||||
|
if ((item->type == type || item->type == RC_ANY) &&
|
||||||
|
(item->parent == NULL || item->parent == parent)) {
|
||||||
|
|
||||||
|
ptr[count].key = calldata.key = item->key;
|
||||||
|
ptr[count].dontfree = (count > 0);
|
||||||
|
ptr[count].value = calldata.value = (items->size ? value : NULL);
|
||||||
|
ptr[count].next = ptr + (count + 1);
|
||||||
|
|
||||||
|
CallCallbacks(&item->initfuncs, &calldata);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
value += item->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
ptr[count-1].next = NULL;
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to free privates at object deletion time.
|
||||||
|
*/
|
||||||
|
_X_EXPORT void
|
||||||
|
dixFreePrivates(PrivateRec *privates)
|
||||||
|
{
|
||||||
|
PrivateRec *ptr, *next;
|
||||||
|
PrivateDescRec *item;
|
||||||
|
PrivateCallbackRec calldata;
|
||||||
|
|
||||||
|
/* first pass calls the delete callbacks */
|
||||||
|
for (ptr = privates; ptr; ptr = ptr->next) {
|
||||||
|
item = findItem(ptr->key);
|
||||||
|
if (item) {
|
||||||
|
calldata.key = ptr->key;
|
||||||
|
calldata.value = ptr->value;
|
||||||
|
CallCallbacks(&item->deletefuncs, &calldata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* second pass frees the memory */
|
||||||
|
ptr = privates;
|
||||||
|
while (ptr) {
|
||||||
|
if (ptr->dontfree)
|
||||||
|
ptr = ptr->next;
|
||||||
|
else {
|
||||||
|
next = ptr->next;
|
||||||
|
while (next && next->dontfree)
|
||||||
|
next = next->next;
|
||||||
|
|
||||||
|
xfree(ptr);
|
||||||
|
ptr = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no more use of privates permitted */
|
||||||
|
*privates = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback registration
|
* Callback registration
|
||||||
*/
|
*/
|
||||||
_X_EXPORT int
|
_X_EXPORT int
|
||||||
dixRegisterPrivateInitFunc(RESTYPE type, int index,
|
dixRegisterPrivateInitFunc(devprivate_key_t *const key,
|
||||||
CallbackProcPtr callback, pointer data)
|
CallbackProcPtr callback, pointer data)
|
||||||
{
|
{
|
||||||
return AddCallback(&GET_DESCRIPTOR(index)->initfuncs, callback, data);
|
PrivateDescRec *item = findItem(key);
|
||||||
|
if (!item)
|
||||||
|
return FALSE;
|
||||||
|
return AddCallback(&item->initfuncs, callback, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
_X_EXPORT int
|
_X_EXPORT int
|
||||||
dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
|
dixRegisterPrivateDeleteFunc(devprivate_key_t *const key,
|
||||||
CallbackProcPtr callback, pointer data)
|
CallbackProcPtr callback, pointer data)
|
||||||
{
|
{
|
||||||
return AddCallback(&GET_DESCRIPTOR(index)->deletefuncs, callback, data);
|
PrivateDescRec *item = findItem(key);
|
||||||
|
if (!item)
|
||||||
|
return FALSE;
|
||||||
|
return AddCallback(&item->deletefuncs, callback, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Table of devPrivates offsets */
|
||||||
* Internal function called from the main loop to reset the subsystem.
|
static unsigned *offsets = NULL;
|
||||||
*/
|
static unsigned offsetsSize = 0;
|
||||||
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.
|
* Specify where the devPrivates field is located in a structure type
|
||||||
*/
|
*/
|
||||||
int
|
_X_EXPORT int
|
||||||
dixUpdatePrivates(void)
|
dixRegisterPrivateOffset(RESTYPE type, unsigned offset)
|
||||||
{
|
{
|
||||||
RESTYPE next = lastResourceType + 1;
|
type = type & TypeMask;
|
||||||
|
|
||||||
/* check if instances table needs to be resized */
|
/* resize offsets table if necessary */
|
||||||
if (next >= instancesSize) {
|
while (type >= offsetsSize) {
|
||||||
RESTYPE size = instancesSize;
|
offsets = (unsigned *)xrealloc(offsets,
|
||||||
|
offsetsSize * 2 * sizeof(unsigned));
|
||||||
while (next >= size)
|
if (!offsets) {
|
||||||
size += PRIV_TAB_INCREMENT;
|
offsetsSize = 0;
|
||||||
|
|
||||||
instances = (char *)xrealloc(instances, size);
|
|
||||||
if (!instances) {
|
|
||||||
instancesSize = 0;
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
memset(instances + instancesSize, 0, size - instancesSize);
|
offsetsSize *= 2;
|
||||||
instancesSize = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offsets[type] = offset;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
_X_EXPORT unsigned
|
||||||
* Internal function called from dixAddResource.
|
dixLookupPrivateOffset(RESTYPE type)
|
||||||
* 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);
|
assert(type & RC_PRIVATES);
|
||||||
ResourcePtr res;
|
type = type & TypeMask;
|
||||||
PrivatePtr ptr;
|
assert(type < offsetsSize);
|
||||||
char *value;
|
return offsets[type];
|
||||||
|
|
||||||
/* 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.
|
* Called from the main loop to reset the subsystem.
|
||||||
* Calls the init functions on a newly allocated resource.
|
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
dixCallPrivateInitFuncs(ResourcePtr res)
|
dixResetPrivates(void)
|
||||||
{
|
{
|
||||||
PrivatePtr ptr = res->privates;
|
PrivateDescRec *next;
|
||||||
PrivateCallbackRec calldata;
|
while (items) {
|
||||||
|
next = items->next;
|
||||||
calldata.resource = res;
|
xfree(items);
|
||||||
while (ptr) {
|
items = next;
|
||||||
calldata.value = ptr->value;
|
|
||||||
calldata.index = ptr->index;
|
|
||||||
CallCallbacks(&GET_DESCRIPTOR(ptr->index)->initfuncs, &calldata);
|
|
||||||
ptr = ptr->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (offsets)
|
||||||
* Internal function called from the various delete resource functions.
|
xfree(offsets);
|
||||||
* 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 */
|
offsetsSize = 16;
|
||||||
ptr = res->privates;
|
offsets = (unsigned *)xalloc(offsetsSize * sizeof(unsigned));
|
||||||
calldata.resource = res;
|
if (!offsets)
|
||||||
while (ptr) {
|
return FALSE;
|
||||||
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 */
|
/* register basic resource offsets */
|
||||||
ptr = res->privates;
|
if (!dixRegisterPrivateOffset(RT_WINDOW, offsetof(WindowRec,devPrivates)))
|
||||||
base = (PrivatePtr)(res + 1);
|
return FALSE;
|
||||||
while (ptr && ptr != base) {
|
|
||||||
next = ptr->next;
|
|
||||||
xfree(ptr);
|
|
||||||
ptr = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove the record from the nexttype linked list and free it*/
|
return TRUE;
|
||||||
if (res->type & RC_PRIVATES) {
|
|
||||||
tmp = (ResourcePtr *)res->value;
|
|
||||||
while (*tmp != res)
|
|
||||||
tmp = &(*tmp)->nexttype;
|
|
||||||
*tmp = (*tmp)->nexttype;
|
|
||||||
}
|
|
||||||
xfree(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -169,6 +169,12 @@ static void RebuildTable(
|
||||||
#define INITHASHSIZE 6
|
#define INITHASHSIZE 6
|
||||||
#define MAXHASHSIZE 11
|
#define MAXHASHSIZE 11
|
||||||
|
|
||||||
|
typedef struct _Resource {
|
||||||
|
struct _Resource *next;
|
||||||
|
XID id;
|
||||||
|
RESTYPE type;
|
||||||
|
pointer value;
|
||||||
|
} ResourceRec, *ResourcePtr;
|
||||||
#define NullResource ((ResourcePtr)NULL)
|
#define NullResource ((ResourcePtr)NULL)
|
||||||
|
|
||||||
typedef struct _ClientResource {
|
typedef struct _ClientResource {
|
||||||
|
|
|
@ -261,10 +261,13 @@ _X_HIDDEN void *dixLookupTab[] = {
|
||||||
SYMFUNC(FreeScratchPixmapHeader)
|
SYMFUNC(FreeScratchPixmapHeader)
|
||||||
/* privates.c */
|
/* privates.c */
|
||||||
SYMFUNC(dixRequestPrivate)
|
SYMFUNC(dixRequestPrivate)
|
||||||
SYMFUNC(dixRequestSinglePrivate)
|
|
||||||
SYMFUNC(dixLookupPrivate)
|
|
||||||
SYMFUNC(dixRegisterPrivateInitFunc)
|
SYMFUNC(dixRegisterPrivateInitFunc)
|
||||||
SYMFUNC(dixRegisterPrivateDeleteFunc)
|
SYMFUNC(dixRegisterPrivateDeleteFunc)
|
||||||
|
SYMFUNC(dixAllocatePrivate)
|
||||||
|
SYMFUNC(dixAllocatePrivates)
|
||||||
|
SYMFUNC(dixFreePrivates)
|
||||||
|
SYMFUNC(dixRegisterPrivateOffset)
|
||||||
|
SYMFUNC(dixLookupPrivateOffset)
|
||||||
SYMFUNC(AllocateExtensionPrivate)
|
SYMFUNC(AllocateExtensionPrivate)
|
||||||
SYMFUNC(AllocateExtensionPrivateIndex)
|
SYMFUNC(AllocateExtensionPrivateIndex)
|
||||||
SYMFUNC(AllocateClientPrivate)
|
SYMFUNC(AllocateClientPrivate)
|
||||||
|
|
|
@ -19,59 +19,141 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
* STUFF FOR PRIVATES
|
* STUFF FOR PRIVATES
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
/*
|
typedef struct _PrivateKey {
|
||||||
* Request private space for your driver/module in all resources of a type.
|
int unused;
|
||||||
* A non-null pScreen argument restricts to resources on a given screen.
|
} devprivate_key_t;
|
||||||
*/
|
|
||||||
extern int
|
typedef struct _Private {
|
||||||
dixRequestPrivate(RESTYPE type, unsigned size, pointer pScreen);
|
devprivate_key_t *key;
|
||||||
|
int dontfree;
|
||||||
|
pointer value;
|
||||||
|
struct _Private *next;
|
||||||
|
} PrivateRec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request private space in just one individual resource object.
|
* Request pre-allocated private space for your driver/module.
|
||||||
|
* A non-null pScreen argument restricts to objects on a given screen.
|
||||||
*/
|
*/
|
||||||
extern int
|
extern int
|
||||||
dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance);
|
dixRequestPrivate(RESTYPE type, devprivate_key_t *const key,
|
||||||
|
unsigned size, pointer pScreen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates a new private and attaches it to an existing object.
|
||||||
|
*/
|
||||||
|
extern pointer *
|
||||||
|
dixAllocatePrivate(PrivateRec **privates, devprivate_key_t *const key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up a private pointer.
|
* Look up a private pointer.
|
||||||
*/
|
*/
|
||||||
extern pointer
|
static _X_INLINE pointer
|
||||||
dixLookupPrivate(RESTYPE type, int index, pointer instance);
|
dixLookupPrivate(PrivateRec **privates, devprivate_key_t *const key)
|
||||||
|
{
|
||||||
|
PrivateRec *rec = *privates;
|
||||||
|
pointer *ptr;
|
||||||
|
|
||||||
|
while (rec) {
|
||||||
|
if (rec->key == key)
|
||||||
|
return rec->value;
|
||||||
|
rec = rec->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = dixAllocatePrivate(privates, key);
|
||||||
|
return ptr ? *ptr : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the address of a private pointer.
|
||||||
|
*/
|
||||||
|
static _X_INLINE pointer *
|
||||||
|
dixLookupPrivateAddr(PrivateRec **privates, devprivate_key_t *const key)
|
||||||
|
{
|
||||||
|
PrivateRec *rec = *privates;
|
||||||
|
|
||||||
|
while (rec) {
|
||||||
|
if (rec->key == key)
|
||||||
|
return &rec->value;
|
||||||
|
rec = rec->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dixAllocatePrivate(privates, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a private pointer.
|
||||||
|
*/
|
||||||
|
static _X_INLINE int
|
||||||
|
dixSetPrivate(PrivateRec **privates, devprivate_key_t *const key, pointer val)
|
||||||
|
{
|
||||||
|
PrivateRec *rec;
|
||||||
|
|
||||||
|
top:
|
||||||
|
rec = *privates;
|
||||||
|
while (rec) {
|
||||||
|
if (rec->key == key) {
|
||||||
|
rec->value = val;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
rec = rec->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dixAllocatePrivate(privates, key))
|
||||||
|
return FALSE;
|
||||||
|
goto top;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register callbacks to be called on private allocation/freeing.
|
* Register callbacks to be called on private allocation/freeing.
|
||||||
* The calldata argument to the callbacks is a PrivateCallbackPtr.
|
* The calldata argument to the callbacks is a PrivateCallbackPtr.
|
||||||
*/
|
*/
|
||||||
typedef struct _PrivateCallback {
|
typedef struct _PrivateCallback {
|
||||||
|
devprivate_key_t *key; /* private registration key */
|
||||||
pointer value; /* pointer to private */
|
pointer value; /* pointer to private */
|
||||||
int index; /* registration index */
|
} PrivateCallbackRec;
|
||||||
ResourcePtr resource; /* resource record (do not modify!) */
|
|
||||||
} PrivateCallbackRec, *PrivateCallbackPtr;
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
dixRegisterPrivateInitFunc(RESTYPE type, int index,
|
dixRegisterPrivateInitFunc(devprivate_key_t *const key,
|
||||||
CallbackProcPtr callback, pointer userdata);
|
CallbackProcPtr callback, pointer userdata);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
|
dixRegisterPrivateDeleteFunc(devprivate_key_t *const key,
|
||||||
CallbackProcPtr callback, pointer userdata);
|
CallbackProcPtr callback, pointer userdata);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal functions
|
* Allocates all pre-requested private space in one chunk.
|
||||||
|
*/
|
||||||
|
extern PrivateRec *
|
||||||
|
dixAllocatePrivates(RESTYPE type, pointer parent);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frees any private space that is not part of an object.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
|
dixFreePrivates(PrivateRec *privates);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resets the subsystem, called from the main loop.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
dixResetPrivates(void);
|
dixResetPrivates(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These next two functions are necessary because the position of
|
||||||
|
* the devPrivates field varies by structure and calling code might
|
||||||
|
* only know the resource type, not the structure definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Looks up the offset where the devPrivates field is located by type.
|
||||||
|
*/
|
||||||
|
extern unsigned
|
||||||
|
dixLookupPrivateOffset(RESTYPE type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specifies the offset where the devPrivates field is located.
|
||||||
|
*/
|
||||||
extern int
|
extern int
|
||||||
dixUpdatePrivates(void);
|
dixRegisterPrivateOffset(RESTYPE type, unsigned offset);
|
||||||
|
|
||||||
extern ResourcePtr
|
|
||||||
dixAllocateResourceRec(RESTYPE type, pointer value, pointer parent);
|
|
||||||
|
|
||||||
extern void
|
|
||||||
dixCallPrivateInitFuncs(ResourcePtr res);
|
|
||||||
|
|
||||||
extern void
|
|
||||||
dixFreeResourceRec(ResourcePtr res);
|
|
||||||
|
|
||||||
#endif /* PRIVATES_H */
|
#endif /* PRIVATES_H */
|
||||||
|
|
|
@ -53,27 +53,10 @@ SOFTWARE.
|
||||||
* STUFF FOR RESOURCES
|
* STUFF FOR RESOURCES
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
/* Resource structures */
|
/* classes for Resource routines */
|
||||||
|
|
||||||
typedef unsigned long RESTYPE;
|
typedef unsigned long RESTYPE;
|
||||||
|
|
||||||
typedef struct _Private {
|
|
||||||
int index;
|
|
||||||
pointer value;
|
|
||||||
struct _Private *next;
|
|
||||||
} PrivateRec, *PrivatePtr;
|
|
||||||
|
|
||||||
typedef struct _Resource {
|
|
||||||
struct _Resource *next;
|
|
||||||
struct _Resource *nexttype;
|
|
||||||
XID id;
|
|
||||||
RESTYPE type;
|
|
||||||
pointer value;
|
|
||||||
PrivatePtr privates;
|
|
||||||
} ResourceRec, *ResourcePtr;
|
|
||||||
|
|
||||||
/* classes for Resource routines */
|
|
||||||
|
|
||||||
#define RC_VANILLA ((RESTYPE)0)
|
#define RC_VANILLA ((RESTYPE)0)
|
||||||
#define RC_CACHED ((RESTYPE)1<<31)
|
#define RC_CACHED ((RESTYPE)1<<31)
|
||||||
#define RC_DRAWABLE ((RESTYPE)1<<30)
|
#define RC_DRAWABLE ((RESTYPE)1<<30)
|
||||||
|
@ -84,8 +67,8 @@ typedef struct _Resource {
|
||||||
*/
|
*/
|
||||||
#define RC_NEVERRETAIN ((RESTYPE)1<<29)
|
#define RC_NEVERRETAIN ((RESTYPE)1<<29)
|
||||||
/* Use class RC_PRIVATES for resources that support extra private data.
|
/* Use class RC_PRIVATES for resources that support extra private data.
|
||||||
* Resources having this class must provide a field of type ResourcePtr
|
* Resources having this class must provide a field of type PrivateRec *.
|
||||||
* at the top of the resource structure, which must be initalized to NULL.
|
* Refer to the X server documentation on devPrivates for the details.
|
||||||
*/
|
*/
|
||||||
#define RC_PRIVATES ((RESTYPE)1<<28)
|
#define RC_PRIVATES ((RESTYPE)1<<28)
|
||||||
#define RC_LASTPREDEF RC_PRIVATES
|
#define RC_LASTPREDEF RC_PRIVATES
|
||||||
|
|
Loading…
Reference in New Issue