Plugin_VideoOGL: X11: Add another display connection to keep the two threads from

eating each others events.

Manifests itself in GPU thread waiting forever for a reply in GL library code(and thus 
a frozen emulation). Most of the time, this can be resolved by creating more events 
(clicking, changing focus), but sometimes it stays stuck.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6218 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
pierre 2010-09-19 23:40:03 +00:00
parent 236f75aac3
commit 6583a3f1e2
2 changed files with 27 additions and 16 deletions

View File

@ -112,22 +112,28 @@ void CreateXWindow (void)
{ {
Atom wmProtocols[1]; Atom wmProtocols[1];
// use evdpy to create the window, so that connection gets the events
// the colormap needs to be created on the same display, because it
// is a client side structure, as well as wmProtocols(or so it seems)
// GLWin.win is a xserver global window handle, so it can be used by both
// display connections
// Setup window attributes // Setup window attributes
GLWin.attr.colormap = XCreateColormap(GLWin.dpy, GLWin.attr.colormap = XCreateColormap(GLWin.evdpy,
GLWin.parent, GLWin.vi->visual, AllocNone); GLWin.parent, GLWin.vi->visual, AllocNone);
GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask; GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask;
GLWin.attr.background_pixel = BlackPixel(GLWin.dpy, GLWin.screen); GLWin.attr.background_pixel = BlackPixel(GLWin.evdpy, GLWin.screen);
GLWin.attr.border_pixel = 0; GLWin.attr.border_pixel = 0;
// Create the window // Create the window
GLWin.win = XCreateWindow(GLWin.dpy, GLWin.parent, GLWin.win = XCreateWindow(GLWin.evdpy, GLWin.parent,
GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual, GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0, GLWin.vi->depth, InputOutput, GLWin.vi->visual,
CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr); CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr);
wmProtocols[0] = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); wmProtocols[0] = XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", True);
XSetWMProtocols(GLWin.dpy, GLWin.win, wmProtocols, 1); XSetWMProtocols(GLWin.evdpy, GLWin.win, wmProtocols, 1);
XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL); XSetStandardProperties(GLWin.evdpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
XMapRaised(GLWin.dpy, GLWin.win); XMapRaised(GLWin.evdpy, GLWin.win);
XSync(GLWin.dpy, True); XSync(GLWin.evdpy, True);
GLWin.xEventThread = new Common::Thread(XEventThread, NULL); GLWin.xEventThread = new Common::Thread(XEventThread, NULL);
} }
@ -136,10 +142,10 @@ void DestroyXWindow(void)
{ {
XUnmapWindow(GLWin.dpy, GLWin.win); XUnmapWindow(GLWin.dpy, GLWin.win);
GLWin.win = 0; GLWin.win = 0;
XFreeColormap(GLWin.dpy, GLWin.attr.colormap);
if (GLWin.xEventThread) if (GLWin.xEventThread)
GLWin.xEventThread->WaitForDeath(); GLWin.xEventThread->WaitForDeath();
GLWin.xEventThread = NULL; GLWin.xEventThread = NULL;
XFreeColormap(GLWin.evdpy, GLWin.attr.colormap);
} }
THREAD_RETURN XEventThread(void *pArg) THREAD_RETURN XEventThread(void *pArg)
@ -148,8 +154,8 @@ THREAD_RETURN XEventThread(void *pArg)
{ {
XEvent event; XEvent event;
KeySym key; KeySym key;
for (int num_events = XPending(GLWin.dpy); num_events > 0; num_events--) { for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--) {
XNextEvent(GLWin.dpy, &event); XNextEvent(GLWin.evdpy, &event);
switch(event.type) { switch(event.type) {
case KeyPress: case KeyPress:
key = XLookupKeysym((XKeyEvent*)&event, 0); key = XLookupKeysym((XKeyEvent*)&event, 0);
@ -202,16 +208,16 @@ THREAD_RETURN XEventThread(void *pArg)
case ConfigureNotify: case ConfigureNotify:
Window winDummy; Window winDummy;
unsigned int borderDummy, depthDummy; unsigned int borderDummy, depthDummy;
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, XGetGeometry(GLWin.evdpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
&GLWin.width, &GLWin.height, &borderDummy, &depthDummy); &GLWin.width, &GLWin.height, &borderDummy, &depthDummy);
s_backbuffer_width = GLWin.width; s_backbuffer_width = GLWin.width;
s_backbuffer_height = GLWin.height; s_backbuffer_height = GLWin.height;
break; break;
case ClientMessage: case ClientMessage:
if ((unsigned long) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", False)) if ((unsigned long) event.xclient.data.l[0] == XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", False))
g_VideoInitialize.pCoreMessage(WM_USER_STOP); g_VideoInitialize.pCoreMessage(WM_USER_STOP);
if ((unsigned long) event.xclient.data.l[0] == XInternAtom(GLWin.dpy, "RESIZE", False)) if ((unsigned long) event.xclient.data.l[0] == XInternAtom(GLWin.evdpy, "RESIZE", False))
XMoveResizeWindow(GLWin.dpy, GLWin.win, event.xclient.data.l[1], XMoveResizeWindow(GLWin.evdpy, GLWin.win, event.xclient.data.l[1],
event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]); event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]);
break; break;
default: default:
@ -343,6 +349,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
None }; None };
GLWin.dpy = XOpenDisplay(0); GLWin.dpy = XOpenDisplay(0);
GLWin.evdpy = XOpenDisplay(0);
GLWin.parent = (Window)g_VideoInitialize.pWindowHandle; GLWin.parent = (Window)g_VideoInitialize.pWindowHandle;
GLWin.screen = DefaultScreen(GLWin.dpy); GLWin.screen = DefaultScreen(GLWin.dpy);
if (GLWin.parent == 0) if (GLWin.parent == 0)
@ -492,6 +499,7 @@ void OpenGL_Shutdown()
{ {
glXDestroyContext(GLWin.dpy, GLWin.ctx); glXDestroyContext(GLWin.dpy, GLWin.ctx);
XCloseDisplay(GLWin.dpy); XCloseDisplay(GLWin.dpy);
XCloseDisplay(GLWin.evdpy);
GLWin.ctx = NULL; GLWin.ctx = NULL;
} }
#endif #endif

View File

@ -78,7 +78,10 @@ typedef struct {
int screen; int screen;
Window win; Window win;
Window parent; Window parent;
Display *dpy; // dpy (mainly) used for glx stuff, evdpy for window events etc.
// used to keep the two threads from eating each others events
// evdpy is to be used by XEventThread only (when it is running)
Display *dpy, *evdpy;
XVisualInfo *vi; XVisualInfo *vi;
GLXContext ctx; GLXContext ctx;
XSetWindowAttributes attr; XSetWindowAttributes attr;