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
* Contributions from Erik Ylvisaker
* 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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
#region --- License ---
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* 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,
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 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.SAMPLES, out samples);
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;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
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,
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
using (new XLock(display))
{
Functions.XFree(visual);
}
return gfx;
}

View file

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

View file

@ -1,4 +1,4 @@
#region --- License ---
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* 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++)
{
IntPtr timestamp_of_last_update;
using (new XLock(API.DefaultDisplay))
{
Functions.XRRTimes(API.DefaultDisplay, screen, out timestamp_of_last_update);
}
lastConfigUpdate.Add(timestamp_of_last_update);
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);
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
// 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)
static int[] FindAvailableDepths(int screen)
{
using (new XLock(API.DefaultDisplay))
{
return Functions.XListDepths(API.DefaultDisplay, screen);
}
}
#endregion
@ -123,7 +133,11 @@ namespace OpenTK.Platform.X11
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)
throw new NotSupportedException("XRandR extensions not available.");
return resolutions;
@ -134,13 +148,16 @@ namespace OpenTK.Platform.X11
#region 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));
ushort rotation = 0;
int size = Functions.XRRConfigCurrentConfiguration(screen_config, out rotation);
short rate = Functions.XRRConfigCurrentRate(screen_config);
rate = Functions.XRRConfigCurrentRate(screen_config);
Functions.XRRFreeScreenConfigInfo(screen_config);
}
return (float)rate;
}
@ -149,9 +166,12 @@ namespace OpenTK.Platform.X11
#region private static int FindCurrentDepth(int screen)
private static int FindCurrentDepth(int screen)
{
using (new XLock(API.DefaultDisplay))
{
return (int)Functions.XDefaultDepth(API.DefaultDisplay, screen);
}
}
#endregion
@ -163,6 +183,8 @@ namespace OpenTK.Platform.X11
{
// If resolution == null, restore to default resolution (new_resolution_index = 0).
using (new XLock(API.DefaultDisplay))
{
int screen = deviceToScreen[device];
IntPtr root = Functions.XRootWindow(API.DefaultDisplay, screen);
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,
current_rotation, (short)(resolution != null ? resolution.RefreshRate : 0), lastConfigUpdate[screen]);
}
}
public bool TryRestoreResolution(DisplayDevice device)
{