summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/glx/xlib
diff options
context:
space:
mode:
authorGeorge Kyriazis <[email protected]>2016-03-02 18:28:00 -0700
committerBrian Paul <[email protected]>2016-03-04 10:57:09 -0700
commit51e562c3ea984f476efc0c4cbd01a4b718f3a007 (patch)
treecbfa5059abedd7f72bb9f2c43c09645a22d121f0 /src/gallium/state_trackers/glx/xlib
parent192ee9adb1c092cf01860d23e13f373fb041c698 (diff)
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 <[email protected]> Reviewed-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers/glx/xlib')
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.c122
1 files changed, 103 insertions, 19 deletions
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
index 2f5e1f5f1a8..2f1bfaec4a0 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -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++;
-
- if (!xmdpy->display && display) {
+ /* 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 */
+
+ /* 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 *****/
/**********************************************************************/