st/xlib: Support unlimited number of display connections

There is a limit of 10 display connections, which was a
problem for apps/tests that were continuously opening/closing display
connections.

This fix uses XAddExtension() and XESetCloseDisplay() to keep track
of the status of the display connections from the X server, freeing
mesa-related data as X displays get destroyed by the X server.

Poster child is the VTK "TimingTests"

Tested-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
George Kyriazis
2016-03-02 18:28:00 -07:00
committed by Brian Paul
parent 192ee9adb1
commit 51e562c3ea

View File

@@ -110,14 +110,6 @@ void xmesa_set_driver( const struct xm_driver *templ )
}
/*
* XXX replace this with a linked list, or better yet, try to attach the
* gallium/mesa extra bits to the X Display object with XAddExtension().
*/
#define MAX_DISPLAYS 10
static struct xmesa_display Displays[MAX_DISPLAYS];
static int NumDisplays = 0;
static int
xmesa_get_param(struct st_manager *smapi,
enum st_manager_param param)
@@ -130,34 +122,125 @@ xmesa_get_param(struct st_manager *smapi,
}
}
/* linked list of XMesaDisplay hooks per display */
typedef struct _XMesaExtDisplayInfo {
struct _XMesaExtDisplayInfo *next;
Display *display;
XExtCodes *codes;
struct xmesa_display mesaDisplay;
} XMesaExtDisplayInfo;
typedef struct _XMesaExtInfo {
XMesaExtDisplayInfo *head;
int ndisplays;
} XMesaExtInfo;
static XMesaExtInfo MesaExtInfo;
/* hook to delete XMesaDisplay on XDestroyDisplay */
static int
xmesa_close_display(Display *display, XExtCodes *codes)
{
XMesaExtDisplayInfo *info, *prev;
assert(MesaExtInfo.ndisplays > 0);
assert(MesaExtInfo.head);
_XLockMutex(_Xglobal_lock);
/* first find display */
prev = NULL;
for (info = MesaExtInfo.head; info; info = info->next) {
if (info->display == display) {
prev = info;
break;
}
}
if (info == NULL) {
/* no display found */
_XUnlockMutex(_Xglobal_lock);
return 0;
}
/* remove display entry from list */
if (prev != MesaExtInfo.head) {
prev->next = info->next;
} else {
MesaExtInfo.head = info->next;
}
MesaExtInfo.ndisplays--;
_XUnlockMutex(_Xglobal_lock);
/* don't forget to clean up mesaDisplay */
XMesaDisplay xmdpy = &info->mesaDisplay;
if (xmdpy->screen) {
xmdpy->screen->destroy(xmdpy->screen);
}
free(xmdpy->smapi);
XFree((char *) info);
return 1;
}
static XMesaDisplay
xmesa_init_display( Display *display )
{
pipe_static_mutex(init_mutex);
XMesaDisplay xmdpy;
int i;
XMesaExtDisplayInfo *info;
if (display == NULL) {
return NULL;
}
pipe_mutex_lock(init_mutex);
/* Look for XMesaDisplay which corresponds to 'display' */
for (i = 0; i < NumDisplays; i++) {
if (Displays[i].display == display) {
/* Look for XMesaDisplay which corresponds to this display */
info = MesaExtInfo.head;
while(info) {
if (info->display == display) {
/* Found it */
pipe_mutex_unlock(init_mutex);
return &Displays[i];
return &info->mesaDisplay;
}
info = info->next;
}
/* Create new XMesaDisplay */
/* Not found. Create new XMesaDisplay */
/* first allocate X-related resources and hook destroy callback */
assert(NumDisplays < MAX_DISPLAYS);
xmdpy = &Displays[NumDisplays];
NumDisplays++;
/* allocate mesa display info */
info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo));
if (info == NULL) {
pipe_mutex_unlock(init_mutex);
return NULL;
}
info->display = display;
info->codes = XAddExtension(display);
if (info->codes == NULL) {
/* could not allocate extension. Fail */
Xfree(info);
pipe_mutex_unlock(init_mutex);
return NULL;
}
XESetCloseDisplay(display, info->codes->extension, xmesa_close_display);
xmdpy = &info->mesaDisplay; /* to be filled out below */
if (!xmdpy->display && display) {
/* chain to the list of displays */
_XLockMutex(_Xglobal_lock);
info->next = MesaExtInfo.head;
MesaExtInfo.head = info;
MesaExtInfo.ndisplays++;
_XUnlockMutex(_Xglobal_lock);
/* now create the new XMesaDisplay info */
if (display) {
xmdpy->display = display;
xmdpy->screen = driver.create_pipe_screen(display);
xmdpy->smapi = CALLOC_STRUCT(st_manager);
xmdpy->pipe = NULL;
if (xmdpy->smapi) {
xmdpy->smapi->screen = xmdpy->screen;
xmdpy->smapi->get_param = xmesa_get_param;
@@ -185,6 +268,7 @@ xmesa_init_display( Display *display )
return xmdpy;
}
/**********************************************************************/
/***** X Utility Functions *****/
/**********************************************************************/