Proper multithreaded locking for Xlib

This commit is contained in:
Jack Andersen 2015-11-11 18:31:59 -10:00
parent 4ee3e0f7aa
commit a2ffab3ff5
3 changed files with 52 additions and 31 deletions

View File

@ -6,5 +6,7 @@
#include "inputdev/DeviceFinder.hpp" #include "inputdev/DeviceFinder.hpp"
#include "inputdev/DolphinSmashAdapter.hpp" #include "inputdev/DolphinSmashAdapter.hpp"
#include "inputdev/DualshockPad.hpp" #include "inputdev/DualshockPad.hpp"
#include "graphicsdev/IGraphicsCommandQueue.hpp"
#include "graphicsdev/IGraphicsDataFactory.hpp"
#endif // BOO_HPP #endif // BOO_HPP

View File

@ -242,6 +242,7 @@ public:
if (FD_ISSET(m_xcbFd, &fds)) if (FD_ISSET(m_xcbFd, &fds))
{ {
XLockDisplay(m_xDisp);
while (XPending(m_xDisp)) while (XPending(m_xDisp))
{ {
XEvent event; XEvent event;
@ -256,6 +257,7 @@ public:
window->second->_incomingEvent(&event); window->second->_incomingEvent(&event);
} }
} }
XUnlockDisplay(m_xDisp);
} }
if (FD_ISSET(m_dbusFd, &fds)) if (FD_ISSET(m_dbusFd, &fds))

View File

@ -196,6 +196,8 @@ public:
m_xDisp(display), m_xDisp(display),
m_lastCtx(lastCtx) m_lastCtx(lastCtx)
{ {
m_dataFactory = new class GLDataFactory(this);
/* Query framebuffer configurations */ /* Query framebuffer configurations */
GLXFBConfig* fbConfigs = nullptr; GLXFBConfig* fbConfigs = nullptr;
int numFBConfigs = 0; int numFBConfigs = 0;
@ -305,51 +307,35 @@ public:
m_timerCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs); m_timerCtx = glXCreateContextAttribsARB(m_xDisp, m_fbconfig, m_glxCtx, True, ContextAttribs);
if (!m_timerCtx) if (!m_timerCtx)
Log.report(LogVisor::FatalError, "unable to make new timer GLX context"); Log.report(LogVisor::FatalError, "unable to make new timer GLX context");
XUnlockDisplay(m_xDisp);
m_commandQueue = _NewGLCommandQueue(this);
XLockDisplay(m_xDisp);
} }
void makeCurrent() void makeCurrent()
{ {
XLockDisplay(m_xDisp);
if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_glxCtx)) if (!glXMakeContextCurrent(m_xDisp, m_glxWindow, m_glxWindow, m_glxCtx))
Log.report(LogVisor::FatalError, "unable to make GLX context current"); Log.report(LogVisor::FatalError, "unable to make GLX context current");
XUnlockDisplay(m_xDisp);
} }
typedef void (*DEBUGPROC)(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
void* userParam);
static void DebugCb(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
void* userParam)
{
fprintf(stderr, "%s\n", message);
}
typedef void(*glDebugMessageCallbackPROC)(DEBUGPROC callback, void* userParam);
void postInit() void postInit()
{ {
GLXExtensionCheck(); GLXExtensionCheck();
XLockDisplay(m_xDisp);
GLXEnableVSync(m_xDisp, m_glxWindow); GLXEnableVSync(m_xDisp, m_glxWindow);
XUnlockDisplay(m_xDisp);
} }
IGraphicsCommandQueue* getCommandQueue() IGraphicsCommandQueue* getCommandQueue()
{ {
if (!m_commandQueue)
m_commandQueue = _NewGLCommandQueue(this);
return m_commandQueue; return m_commandQueue;
} }
IGraphicsDataFactory* getDataFactory() IGraphicsDataFactory* getDataFactory()
{ {
if (!m_dataFactory)
m_dataFactory = new class GLDataFactory(this);
return m_dataFactory; return m_dataFactory;
} }
@ -491,9 +477,11 @@ public:
~WindowXlib() ~WindowXlib()
{ {
XLockDisplay(m_xDisp);
XUnmapWindow(m_xDisp, m_windowId); XUnmapWindow(m_xDisp, m_windowId);
XDestroyWindow(m_xDisp, m_windowId); XDestroyWindow(m_xDisp, m_windowId);
XFreeColormap(m_xDisp, m_colormapId); XFreeColormap(m_xDisp, m_colormapId);
XUnlockDisplay(m_xDisp);
APP->_deletedWindow(this); APP->_deletedWindow(this);
} }
@ -504,14 +492,16 @@ public:
void showWindow() void showWindow()
{ {
XLockDisplay(m_xDisp);
XMapWindow(m_xDisp, m_windowId); XMapWindow(m_xDisp, m_windowId);
XFlush(m_xDisp); XUnlockDisplay(m_xDisp);
} }
void hideWindow() void hideWindow()
{ {
XLockDisplay(m_xDisp);
XUnmapWindow(m_xDisp, m_windowId); XUnmapWindow(m_xDisp, m_windowId);
XFlush(m_xDisp); XUnlockDisplay(m_xDisp);
} }
std::string getTitle() std::string getTitle()
@ -521,8 +511,11 @@ public:
int actualFormat; int actualFormat;
unsigned long bytes; unsigned long bytes;
unsigned char* string = nullptr; unsigned char* string = nullptr;
if (XGetWindowProperty(m_xDisp, m_windowId, XA_WM_NAME, 0, ~0l, False, XLockDisplay(m_xDisp);
XA_STRING, &actualType, &actualFormat, &nitems, &bytes, &string) == Success) int ret = XGetWindowProperty(m_xDisp, m_windowId, XA_WM_NAME, 0, ~0l, False,
XA_STRING, &actualType, &actualFormat, &nitems, &bytes, &string);
XUnlockDisplay(m_xDisp);
if (ret == Success)
{ {
std::string retval((const char*)string); std::string retval((const char*)string);
XFree(string); XFree(string);
@ -534,8 +527,10 @@ public:
void setTitle(const std::string& title) void setTitle(const std::string& title)
{ {
const unsigned char* c_title = (unsigned char*)title.c_str(); const unsigned char* c_title = (unsigned char*)title.c_str();
XLockDisplay(m_xDisp);
XChangeProperty(m_xDisp, m_windowId, XA_WM_NAME, XA_STRING, 8, XChangeProperty(m_xDisp, m_windowId, XA_WM_NAME, XA_STRING, 8,
PropModeReplace, c_title, title.length()); PropModeReplace, c_title, title.length());
XUnlockDisplay(m_xDisp);
} }
void setWindowFrameDefault() void setWindowFrameDefault()
@ -544,13 +539,17 @@ public:
Screen* screen = DefaultScreenOfDisplay(m_xDisp); Screen* screen = DefaultScreenOfDisplay(m_xDisp);
genFrameDefault(screen, x, y, w, h); genFrameDefault(screen, x, y, w, h);
XWindowChanges values = {(int)x, (int)y, (int)w, (int)h}; XWindowChanges values = {(int)x, (int)y, (int)w, (int)h};
XLockDisplay(m_xDisp);
XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values); XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values);
XUnlockDisplay(m_xDisp);
} }
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{ {
XWindowAttributes attrs; XWindowAttributes attrs;
XLockDisplay(m_xDisp);
XGetWindowAttributes(m_xDisp, m_windowId, &attrs); XGetWindowAttributes(m_xDisp, m_windowId, &attrs);
XUnlockDisplay(m_xDisp);
xOut = attrs.x; xOut = attrs.x;
yOut = attrs.y; yOut = attrs.y;
wOut = attrs.width; wOut = attrs.width;
@ -560,7 +559,9 @@ public:
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{ {
XWindowAttributes attrs; XWindowAttributes attrs;
XLockDisplay(m_xDisp);
XGetWindowAttributes(m_xDisp, m_windowId, &attrs); XGetWindowAttributes(m_xDisp, m_windowId, &attrs);
XUnlockDisplay(m_xDisp);
xOut = attrs.x; xOut = attrs.x;
yOut = attrs.y; yOut = attrs.y;
wOut = attrs.width; wOut = attrs.width;
@ -570,13 +571,17 @@ public:
void setWindowFrame(float x, float y, float w, float h) void setWindowFrame(float x, float y, float w, float h)
{ {
XWindowChanges values = {(int)x, (int)y, (int)w, (int)h}; XWindowChanges values = {(int)x, (int)y, (int)w, (int)h};
XLockDisplay(m_xDisp);
XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values); XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values);
XUnlockDisplay(m_xDisp);
} }
void setWindowFrame(int x, int y, int w, int h) void setWindowFrame(int x, int y, int w, int h)
{ {
XWindowChanges values = {x, y, w, h}; XWindowChanges values = {x, y, w, h};
XLockDisplay(m_xDisp);
XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values); XConfigureWindow(m_xDisp, m_windowId, CWX|CWY|CWWidth|CWHeight, &values);
XUnlockDisplay(m_xDisp);
} }
float getVirtualPixelFactor() const float getVirtualPixelFactor() const
@ -593,8 +598,11 @@ public:
unsigned long bytes; unsigned long bytes;
Atom* vals = nullptr; Atom* vals = nullptr;
bool fullscreen = false; bool fullscreen = false;
if (XGetWindowProperty(m_xDisp, m_windowId, S_ATOMS->m_netwmState, 0, ~0l, False, XLockDisplay(m_xDisp);
XA_ATOM, &actualType, &actualFormat, &nitems, &bytes, (unsigned char**)&vals) == Success) int ret = XGetWindowProperty(m_xDisp, m_windowId, S_ATOMS->m_netwmState, 0, ~0l, False,
XA_ATOM, &actualType, &actualFormat, &nitems, &bytes, (unsigned char**)&vals);
XUnlockDisplay(m_xDisp);
if (ret == Success)
{ {
for (int i=0 ; i<nitems ; ++i) for (int i=0 ; i<nitems ; ++i)
{ {
@ -639,7 +647,9 @@ public:
if (style & STYLE_CLOSE) if (style & STYLE_CLOSE)
wmHints.functions |= MWM_FUNC_CLOSE; wmHints.functions |= MWM_FUNC_CLOSE;
XLockDisplay(m_xDisp);
XChangeProperty(m_xDisp, m_windowId, S_ATOMS->m_motifWmHints, S_ATOMS->m_motifWmHints, 32, PropModeReplace, (unsigned char*)&wmHints, 5); XChangeProperty(m_xDisp, m_windowId, S_ATOMS->m_motifWmHints, S_ATOMS->m_motifWmHints, 32, PropModeReplace, (unsigned char*)&wmHints, 5);
XUnlockDisplay(m_xDisp);
} }
m_styleFlags = style; m_styleFlags = style;
@ -665,8 +675,10 @@ public:
fsEvent.xclient.data.l[0] = fs; fsEvent.xclient.data.l[0] = fs;
fsEvent.xclient.data.l[1] = S_ATOMS->m_netwmStateFullscreen; fsEvent.xclient.data.l[1] = S_ATOMS->m_netwmStateFullscreen;
fsEvent.xclient.data.l[2] = 0; fsEvent.xclient.data.l[2] = 0;
XLockDisplay(m_xDisp);
XSendEvent(m_xDisp, DefaultRootWindow(m_xDisp), False, XSendEvent(m_xDisp, DefaultRootWindow(m_xDisp), False,
StructureNotifyMask | SubstructureRedirectMask, (XEvent*)&fsEvent); StructureNotifyMask | SubstructureRedirectMask, (XEvent*)&fsEvent);
XUnlockDisplay(m_xDisp);
m_inFs = fs; m_inFs = fs;
} }
@ -1127,7 +1139,9 @@ public:
bool _isWindowMapped() bool _isWindowMapped()
{ {
XWindowAttributes attr; XWindowAttributes attr;
XLockDisplay(m_xDisp);
XGetWindowAttributes(m_xDisp, m_windowId, &attr); XGetWindowAttributes(m_xDisp, m_windowId, &attr);
XUnlockDisplay(m_xDisp);
return attr.map_state != IsUnmapped; return attr.map_state != IsUnmapped;
} }
}; };
@ -1136,7 +1150,10 @@ IWindow* _WindowXlibNew(const std::string& title,
Display* display, int defaultScreen, Display* display, int defaultScreen,
GLXContext lastCtx) GLXContext lastCtx)
{ {
return new WindowXlib(title, display, defaultScreen, lastCtx); XLockDisplay(display);
IWindow* ret = new WindowXlib(title, display, defaultScreen, lastCtx);
XUnlockDisplay(display);
return ret;
} }
} }