Use more aggressive xlib locking following the advice of the multithreaded X manpages (needs work).

This commit is contained in:
the_fiddler 2009-11-02 22:37:13 +00:00
parent 2a1924c62c
commit 974641086c
7 changed files with 158 additions and 99 deletions

View file

@ -1,4 +1,4 @@
#region --- License --- #region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* Contributions from Erik Ylvisaker * Contributions from Erik Ylvisaker
* See license.txt for license info * See license.txt for license info
@ -1589,6 +1589,23 @@ XF86VidModeGetGammaRampSize(
} }
} }
*/ */
struct XLock : IDisposable
{
readonly IntPtr Display;
public XLock(IntPtr display)
: this()
{
Functions.XLockDisplay(display);
Display = display;
}
public void Dispose()
{
Functions.XUnlockDisplay(Display);
}
}
} }
#pragma warning restore 3019 #pragma warning restore 3019

View file

@ -1,4 +1,4 @@
#region --- License --- #region --- License ---
/* Licensed under the MIT/X11 license. /* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team. * Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution. * This notice may not be removed from any source distribution.
@ -77,10 +77,18 @@ namespace OpenTK.Platform.X11
internal static partial class Functions internal static partial class Functions
{ {
public static readonly object Lock = new object(); public static readonly object Lock = API.Lock;
[DllImport("libX11", EntryPoint = "XOpenDisplay")] [DllImport("libX11", EntryPoint = "XOpenDisplay")]
public extern static IntPtr XOpenDisplay(IntPtr display); extern static IntPtr sys_XOpenDisplay(IntPtr display);
public static IntPtr XOpenDisplay(IntPtr display)
{
lock (Lock)
{
return sys_XOpenDisplay(display);
}
}
[DllImport("libX11", EntryPoint = "XCloseDisplay")] [DllImport("libX11", EntryPoint = "XCloseDisplay")]
public extern static int XCloseDisplay(IntPtr display); public extern static int XCloseDisplay(IntPtr display);
[DllImport("libX11", EntryPoint = "XSynchronize")] [DllImport("libX11", EntryPoint = "XSynchronize")]

View file

@ -130,10 +130,13 @@ namespace OpenTK.Platform.X11
else else
Debug.WriteLine("success!"); Debug.WriteLine("success!");
using (new XLock(Display))
{
Functions.XFree((IntPtr)fbconfigs); Functions.XFree((IntPtr)fbconfigs);
} }
} }
} }
}
if (Handle == ContextHandle.Zero) if (Handle == ContextHandle.Zero)
{ {

View file

@ -122,7 +122,7 @@ namespace OpenTK.Platform.X11
Debug.Indent(); Debug.Indent();
lock (API.Lock) using (new XLock(window.Display))
{ {
if (!mode.Index.HasValue) if (!mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
@ -164,7 +164,7 @@ namespace OpenTK.Platform.X11
hints.base_width = width; hints.base_width = width;
hints.base_height = height; hints.base_height = height;
hints.flags = (IntPtr)(XSizeHintsFlags.PSize | XSizeHintsFlags.PPosition); hints.flags = (IntPtr)(XSizeHintsFlags.PSize | XSizeHintsFlags.PPosition);
lock (API.Lock) using (new XLock(window.Display))
{ {
Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints); Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints);
@ -194,20 +194,17 @@ namespace OpenTK.Platform.X11
Debug.Indent(); Debug.Indent();
// Open a display connection to the X server, and obtain the screen and root window. // Open a display connection to the X server, and obtain the screen and root window.
window.Display = API.DefaultDisplay; window.Display = Functions.XOpenDisplay(IntPtr.Zero);
//window.Display = API.DefaultDisplay;
if (window.Display == IntPtr.Zero) if (window.Display == IntPtr.Zero)
throw new Exception("Could not open connection to X"); throw new Exception("Could not open connection to X");
try using (new XLock(window.Display))
{ {
Functions.XLockDisplay(window.Display); Functions.XLockDisplay(window.Display);
window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen;
window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow; window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow;
} }
finally
{
Functions.XUnlockDisplay(window.Display);
}
Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen, Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen,
window.RootWindow); window.RootWindow);
@ -231,6 +228,8 @@ namespace OpenTK.Platform.X11
/// Registers the necessary atoms for GameWindow. /// Registers the necessary atoms for GameWindow.
/// </summary> /// </summary>
private void RegisterAtoms(X11WindowInfo window) private void RegisterAtoms(X11WindowInfo window)
{
using (new XLock(window.Display))
{ {
Debug.WriteLine("Registering atoms."); Debug.WriteLine("Registering atoms.");
_atom_wm_destroy = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true); _atom_wm_destroy = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true);
@ -267,6 +266,7 @@ namespace OpenTK.Platform.X11
// //WMTitle = atoms[offset++]; // //WMTitle = atoms[offset++];
// //UTF8String = atoms[offset++]; // //UTF8String = atoms[offset++];
} }
}
#endregion #endregion

View file

@ -1,4 +1,4 @@
#region --- License --- #region --- License ---
/* Licensed under the MIT/X11 license. /* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team. * Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution. * This notice may not be removed from any source distribution.
@ -35,7 +35,8 @@ namespace OpenTK.Platform.X11
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum,
int buffers, bool stereo) int buffers, bool stereo)
{ {
GraphicsMode gfx; // The actual GraphicsMode that will be selected. GraphicsMode gfx;
// The actual GraphicsMode that will be selected.
IntPtr visual = IntPtr.Zero; IntPtr visual = IntPtr.Zero;
IntPtr display = API.DefaultDisplay; IntPtr display = API.DefaultDisplay;
@ -66,7 +67,8 @@ namespace OpenTK.Platform.X11
Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil); Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil);
Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples); Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples);
Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers); Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers);
++buffers; // the above lines returns 0 - false and 1 - true. ++buffers;
// the above lines returns 0 - false and 1 - true.
int st; int st;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st); Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
stereo = st != 0; stereo = st != 0;
@ -74,7 +76,10 @@ namespace OpenTK.Platform.X11
gfx = new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples, gfx = new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples,
new ColorFormat(ar, ag, ab, aa), buffers, stereo); new ColorFormat(ar, ag, ab, aa), buffers, stereo);
using (new XLock(display))
{
Functions.XFree(visual); Functions.XFree(visual);
}
return gfx; return gfx;
} }

View file

@ -1,4 +1,4 @@
#region --- License --- #region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info * See license.txt for license info
*/ */
@ -61,6 +61,8 @@ namespace OpenTK.Platform.X11
mouse.NumberOfWheels = 1; mouse.NumberOfWheels = 1;
dummy_mice_list.Add(mouse); dummy_mice_list.Add(mouse);
using (new XLock(window.Display))
{
// Init keyboard // Init keyboard
API.DisplayKeycodes(window.Display, ref firstKeyCode, ref lastKeyCode); API.DisplayKeycodes(window.Display, ref firstKeyCode, ref lastKeyCode);
Debug.Print("First keycode: {0}, last {1}", firstKeyCode, lastKeyCode); Debug.Print("First keycode: {0}, last {1}", firstKeyCode, lastKeyCode);
@ -85,6 +87,7 @@ namespace OpenTK.Platform.X11
// be reset before the program exits. // be reset before the program exits.
bool supported; bool supported;
Functions.XkbSetDetectableAutoRepeat(window.Display, true, out supported); Functions.XkbSetDetectableAutoRepeat(window.Display, true, out supported);
}
Debug.Unindent(); Debug.Unindent();
} }

View file

@ -1,4 +1,4 @@
#region --- License --- #region --- License ---
/* Licensed under the MIT/X11 license. /* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team. * Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution. * This notice may not be removed from any source distribution.
@ -42,7 +42,10 @@ namespace OpenTK.Platform.X11
for (int screen = 0; screen < API.ScreenCount; screen++) for (int screen = 0; screen < API.ScreenCount; screen++)
{ {
IntPtr timestamp_of_last_update; IntPtr timestamp_of_last_update;
using (new XLock(API.DefaultDisplay))
{
Functions.XRRTimes(API.DefaultDisplay, screen, out timestamp_of_last_update); Functions.XRRTimes(API.DefaultDisplay, screen, out timestamp_of_last_update);
}
lastConfigUpdate.Add(timestamp_of_last_update); lastConfigUpdate.Add(timestamp_of_last_update);
List<DisplayResolution> available_res = new List<DisplayResolution>(); List<DisplayResolution> available_res = new List<DisplayResolution>();
@ -60,7 +63,11 @@ namespace OpenTK.Platform.X11
Debug.Print("[Warning] XRandR returned an invalid resolution ({0}) for display device {1}", size, screen); Debug.Print("[Warning] XRandR returned an invalid resolution ({0}) for display device {1}", size, screen);
continue; continue;
} }
short[] rates = Functions.XRRRates(API.DefaultDisplay, screen, resolution_count); short[] rates = null;
using (new XLock(API.DefaultDisplay))
{
rates = Functions.XRRRates(API.DefaultDisplay, screen, resolution_count);
}
// It seems that XRRRates returns 0 for modes that are larger than the screen // It seems that XRRRates returns 0 for modes that are larger than the screen
// can support, as well as for all supported modes. On Ubuntu 7.10 the tool // can support, as well as for all supported modes. On Ubuntu 7.10 the tool
@ -113,9 +120,12 @@ namespace OpenTK.Platform.X11
#region static int[] FindAvailableDepths(int screen) #region static int[] FindAvailableDepths(int screen)
static int[] FindAvailableDepths(int screen) static int[] FindAvailableDepths(int screen)
{
using (new XLock(API.DefaultDisplay))
{ {
return Functions.XListDepths(API.DefaultDisplay, screen); return Functions.XListDepths(API.DefaultDisplay, screen);
} }
}
#endregion #endregion
@ -123,7 +133,11 @@ namespace OpenTK.Platform.X11
static XRRScreenSize[] FindAvailableResolutions(int screen) static XRRScreenSize[] FindAvailableResolutions(int screen)
{ {
XRRScreenSize[] resolutions = Functions.XRRSizes(API.DefaultDisplay, screen); XRRScreenSize[] resolutions = null;
using (new XLock(API.DefaultDisplay))
{
resolutions = Functions.XRRSizes(API.DefaultDisplay, screen);
}
if (resolutions == null) if (resolutions == null)
throw new NotSupportedException("XRandR extensions not available."); throw new NotSupportedException("XRandR extensions not available.");
return resolutions; return resolutions;
@ -134,13 +148,16 @@ namespace OpenTK.Platform.X11
#region static float FindCurrentRefreshRate(int screen) #region static float FindCurrentRefreshRate(int screen)
static float FindCurrentRefreshRate(int screen) static float FindCurrentRefreshRate(int screen)
{
short rate = 0;
using (new XLock(API.DefaultDisplay))
{ {
IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, Functions.XRootWindow(API.DefaultDisplay, screen)); IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, Functions.XRootWindow(API.DefaultDisplay, screen));
ushort rotation = 0; ushort rotation = 0;
int size = Functions.XRRConfigCurrentConfiguration(screen_config, out rotation); int size = Functions.XRRConfigCurrentConfiguration(screen_config, out rotation);
short rate = Functions.XRRConfigCurrentRate(screen_config); rate = Functions.XRRConfigCurrentRate(screen_config);
Functions.XRRFreeScreenConfigInfo(screen_config); Functions.XRRFreeScreenConfigInfo(screen_config);
}
return (float)rate; return (float)rate;
} }
@ -149,9 +166,12 @@ namespace OpenTK.Platform.X11
#region private static int FindCurrentDepth(int screen) #region private static int FindCurrentDepth(int screen)
private static int FindCurrentDepth(int screen) private static int FindCurrentDepth(int screen)
{
using (new XLock(API.DefaultDisplay))
{ {
return (int)Functions.XDefaultDepth(API.DefaultDisplay, screen); return (int)Functions.XDefaultDepth(API.DefaultDisplay, screen);
} }
}
#endregion #endregion
@ -163,6 +183,8 @@ namespace OpenTK.Platform.X11
{ {
// If resolution == null, restore to default resolution (new_resolution_index = 0). // If resolution == null, restore to default resolution (new_resolution_index = 0).
using (new XLock(API.DefaultDisplay))
{
int screen = deviceToScreen[device]; int screen = deviceToScreen[device];
IntPtr root = Functions.XRootWindow(API.DefaultDisplay, screen); IntPtr root = Functions.XRootWindow(API.DefaultDisplay, screen);
IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, root); IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, root);
@ -182,6 +204,7 @@ namespace OpenTK.Platform.X11
return 0 == Functions.XRRSetScreenConfigAndRate(API.DefaultDisplay, screen_config, root, new_resolution_index, return 0 == Functions.XRRSetScreenConfigAndRate(API.DefaultDisplay, screen_config, root, new_resolution_index,
current_rotation, (short)(resolution != null ? resolution.RefreshRate : 0), lastConfigUpdate[screen]); current_rotation, (short)(resolution != null ? resolution.RefreshRate : 0), lastConfigUpdate[screen]);
} }
}
public bool TryRestoreResolution(DisplayDevice device) public bool TryRestoreResolution(DisplayDevice device)
{ {