Use one display connection for all X11 communication. Seems to fix (not 100%) the crash problems encountered.

This commit is contained in:
the_fiddler 2008-03-24 13:12:02 +00:00
parent 5b4bed3a09
commit ef16998dca
8 changed files with 168 additions and 96 deletions

View file

@ -2,7 +2,7 @@
/* 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.
* See license.txt for licensing detailed licensing details. * See license.txt for licensing details.
*/ */
#endregion #endregion

View file

@ -338,9 +338,9 @@ namespace OpenTK.Graphics
{ {
Form form = new Form(); Form form = new Form();
form.ShowInTaskbar = false; form.ShowInTaskbar = false;
form.StartPosition = FormStartPosition.Manual; form.StartPosition = FormStartPosition.Manual;
form.FormBorderStyle = FormBorderStyle.None;
form.WindowState = FormWindowState.Maximized; form.WindowState = FormWindowState.Maximized;
form.FormBorderStyle = FormBorderStyle.None;
form.TopMost = true; form.TopMost = true;
form.BackColor = System.Drawing.Color.Black; form.BackColor = System.Drawing.Color.Black;
@ -353,9 +353,13 @@ namespace OpenTK.Graphics
void MoveToStartPositions() void MoveToStartPositions()
{ {
//int count = 0; int count = 0;
//foreach (Screen s in Screen.AllScreens) foreach (Screen s in Screen.AllScreens)
// forms[count++].Location = new System.Drawing.Point(s.Bounds.X, s.Bounds.Y); {
// forms[count++].Location = new System.Drawing.Point(s.Bounds.X, s.Bounds.Y);
//forms[count].Size = new System.Drawing.Size(4096, 4096);
count++;
}
} }
bool FadedOut bool FadedOut

View file

@ -8,7 +8,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Diagnostics;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
@ -38,7 +39,6 @@ namespace OpenTK.Platform.X11
using Rotation = System.UInt16; using Rotation = System.UInt16;
using Status = System.Int32; using Status = System.Int32;
using SizeID = System.UInt16; using SizeID = System.UInt16;
using System.Diagnostics;
#endregion #endregion
@ -57,37 +57,56 @@ namespace OpenTK.Platform.X11
static int screenCount; static int screenCount;
internal static Display DefaultDisplay { get { return defaultDisplay; } } internal static Display DefaultDisplay { get { return defaultDisplay; } }
internal static int DefaultScreen { get { return defaultScreen; } } //internal static int DefaultScreen { get { return defaultScreen; } }
internal static Window RootWindow { get { return rootWindow; } } //internal static Window RootWindow { get { return rootWindow; } }
internal static int ScreenCount { get { return screenCount; } } internal static int ScreenCount { get { return screenCount; } }
internal static object Lock = new object();
#endregion #endregion
static API() static API()
{ {
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
defaultDisplay = Functions.XOpenDisplay(IntPtr.Zero);
defaultScreen = Functions.XDefaultScreen(DefaultDisplay); //using (System.Windows.Forms.Control c = new System.Windows.Forms.Control()) { }
rootWindow = Functions.XRootWindow(DefaultDisplay, DefaultScreen); //Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
//defaultDisplay = (IntPtr)xplatui.GetField("DisplayHandle", System.Reflection.BindingFlags.Static |
// System.Reflection.BindingFlags.NonPublic).GetValue(null);
defaultDisplay = Functions.XOpenDisplay(IntPtr.Zero);
if (defaultDisplay == IntPtr.Zero)
throw new PlatformException("Could not establish connection to the X-Server.");
//defaultScreen = Functions.XDefaultScreen(DefaultDisplay);
//rootWindow = Functions.XRootWindow(DefaultDisplay, DefaultScreen);
screenCount = Functions.XScreenCount(DefaultDisplay); screenCount = Functions.XScreenCount(DefaultDisplay);
Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}", //Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}",
DefaultDisplay, DefaultScreen, RootWindow, ScreenCount); // DefaultDisplay, DefaultScreen, RootWindow, ScreenCount);
Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount);
} }
static void CurrentDomain_ProcessExit(object sender, EventArgs e) static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{ {
if (defaultDisplay != IntPtr.Zero) { Functions.XCloseDisplay(defaultDisplay); defaultDisplay = IntPtr.Zero; } if (defaultDisplay != IntPtr.Zero)
{
Functions.XCloseDisplay(defaultDisplay);
defaultDisplay = IntPtr.Zero;
defaultScreen = 0;
rootWindow = IntPtr.Zero;
}
} }
// Display management // Display management
[DllImport(_dll_name, EntryPoint = "XOpenDisplay")] //[DllImport(_dll_name, EntryPoint = "XOpenDisplay")]
extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name); //extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name);
[DllImport(_dll_name, EntryPoint = "XCloseDisplay")] //[DllImport(_dll_name, EntryPoint = "XCloseDisplay")]
extern public static void CloseDisplay(Display display); //extern public static void CloseDisplay(Display display);
[DllImport(_dll_name, EntryPoint = "XCreateColormap")] //[DllImport(_dll_name, EntryPoint = "XCreateColormap")]
extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc); //extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc);
#region Window handling #region Window handling

View file

@ -12,7 +12,36 @@ using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
#region Types
// using XID = System.Int32;
using Window = System.IntPtr;
using Drawable = System.IntPtr;
using Font = System.IntPtr;
using Pixmap = System.IntPtr;
using Cursor = System.IntPtr;
using Colormap = System.IntPtr;
using GContext = System.IntPtr;
using KeySym = System.IntPtr;
using Mask = System.IntPtr;
using Atom = System.IntPtr;
using VisualID = System.IntPtr;
using Time = System.UInt32;
using KeyCode = System.Byte; // Or maybe ushort?
using Display = System.IntPtr;
using XPointer = System.IntPtr;
// Randr and Xrandr
using Bool = System.Boolean;
using XRRScreenConfiguration = System.IntPtr; // opaque datatype
using Rotation = System.UInt16;
using Status = System.Int32;
using SizeID = System.UInt16;
#endregion
internal static partial class Functions internal static partial class Functions
{ {
public static readonly object Lock = new object(); public static readonly object Lock = new object();
@ -337,13 +366,15 @@ namespace OpenTK.Platform.X11
public extern static void XPeekEvent(IntPtr display, ref XEvent xevent); public extern static void XPeekEvent(IntPtr display, ref XEvent xevent);
[DllImport("libX11", EntryPoint = "XGetVisualInfo")] [DllImport("libX11", EntryPoint = "XGetVisualInfo")]
static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
out int nitems);
public static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems) public static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems)
{ {
return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems); return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems);
} }
[DllImport("libX11")]
public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc);
} }
} }

View file

@ -39,7 +39,7 @@ namespace OpenTK.Platform.X11
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, window.VisualInfo.visual); .SetValue(null, window.VisualInfo.visual);
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0)); .SetValue(null, Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0));
} }
#region --- IGLControl Members --- #region --- IGLControl Members ---

View file

@ -1,6 +1,8 @@
#region --- License --- #region --- License ---
/* Copyright (c) 2007 Stefanos Apostolopoulos /* Licensed under the MIT/X11 license.
* See license.txt for license info * Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/ */
#endregion #endregion
@ -93,7 +95,7 @@ namespace OpenTK.Platform.X11
// System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
// 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.OpenDisplay(null); // null == default display //window.Display = API.DefaultDisplay; window.Display = API.DefaultDisplay;//Functions.XOpenDisplay(IntPtr.Zero); // IntPtr.Zero == default display
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");
window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen;
@ -157,13 +159,11 @@ namespace OpenTK.Platform.X11
XSetWindowAttributes attributes = new XSetWindowAttributes(); XSetWindowAttributes attributes = new XSetWindowAttributes();
attributes.background_pixel = IntPtr.Zero; attributes.background_pixel = IntPtr.Zero;
attributes.border_pixel = IntPtr.Zero; attributes.border_pixel = IntPtr.Zero;
attributes.colormap = attributes.colormap = Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/);
API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask |
window.EventMask = EventMask.KeyReleaseMask | EventMask.KeyPressMask |
EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask |
EventMask.KeyReleaseMask | EventMask.KeyPressMask | EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask |
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask;
attributes.event_mask = (IntPtr)window.EventMask; attributes.event_mask = (IntPtr)window.EventMask;
uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask |
@ -664,10 +664,10 @@ namespace OpenTK.Platform.X11
{ {
if (window != null) if (window != null)
{ {
if (window.WindowHandle != IntPtr.Zero) if (window.WindowHandle != IntPtr.Zero)
Functions.XDestroyWindow(window.Display, window.WindowHandle); Functions.XDestroyWindow(window.Display, window.WindowHandle);
if (window.Display != IntPtr.Zero) //if (window.Display != IntPtr.Zero)
Functions.XCloseDisplay(window.Display); // Functions.XCloseDisplay(window.Display);
window = null; window = null;
} }

View file

@ -25,7 +25,11 @@ 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)
{ {
List<int> visualAttributes = new List<int>(); GraphicsMode gfx; // The actual GraphicsMode that will be selected.
List<int> visualAttributes = new List<int>();
IntPtr visual;
Debug.Print("Bits per pixel: {0}", color.BitsPerPixel);
if (color.BitsPerPixel > 0) if (color.BitsPerPixel > 0)
{ {
@ -40,6 +44,8 @@ namespace OpenTK.Platform.X11
visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE);
visualAttributes.Add(color.Alpha); visualAttributes.Add(color.Alpha);
} }
Debug.Print("Depth: {0}", depth);
if (depth > 0) if (depth > 0)
{ {
@ -71,56 +77,70 @@ namespace OpenTK.Platform.X11
if (stereo) if (stereo)
visualAttributes.Add((int)GLXAttribute.STEREO); visualAttributes.Add((int)GLXAttribute.STEREO);
visualAttributes.Add((int)0); visualAttributes.Add((int)0);
// Select a visual that matches the parameters set by the user.
lock (API.Lock)
{
IntPtr display = API.DefaultDisplay; //Functions.XOpenDisplay(IntPtr.Zero);
int screen = Functions.XDefaultScreen(display);
IntPtr root = Functions.XRootWindow(display, screen);
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root);
// Prepare Windows.Forms for creating OpenGL drawables. visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray());
// We reuse the display connection.
// TODO: Multiple screens.
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
IntPtr root = (IntPtr)xplatui.GetField("RootWindow",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
int screen = (int)xplatui.GetField("ScreenNo",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); if (visual == IntPtr.Zero)
throw new GraphicsContextException("Requested GraphicsMode not available.");
IntPtr visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray()); XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo));
if (visual == IntPtr.Zero) // See what we *really* got:
throw new GraphicsContextException("Requested GraphicsMode not available."); int r, g, b, a;
Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a);
Glx.GetConfig(display, ref info, GLXAttribute.RED_SIZE, out r);
Glx.GetConfig(display, ref info, GLXAttribute.GREEN_SIZE, out g);
Glx.GetConfig(display, ref info, GLXAttribute.BLUE_SIZE, out b);
int ar, ag, ab, aa;
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_ALPHA_SIZE, out aa);
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_RED_SIZE, out ar);
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag);
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_BLUE_SIZE, out ab);
Glx.GetConfig(display, ref info, GLXAttribute.DEPTH_SIZE, out depth);
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.
int st;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
stereo = st != 0;
XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo)); gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples,
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
// See what we *really* got:
int r, g, b, a; //Functions.XCloseDisplay(display);
Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a); }
Glx.GetConfig(display, ref info, GLXAttribute.RED_SIZE, out r);
Glx.GetConfig(display, ref info, GLXAttribute.GREEN_SIZE, out g); // Prepare Windows.Forms for creating OpenGL drawables.
Glx.GetConfig(display, ref info, GLXAttribute.BLUE_SIZE, out b); lock (API.Lock)
int ar, ag, ab, aa; {
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_ALPHA_SIZE, out aa); Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_RED_SIZE, out ar); IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle",
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag); System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_BLUE_SIZE, out ab); IntPtr root = (IntPtr)xplatui.GetField("RootWindow",
Glx.GetConfig(display, ref info, GLXAttribute.DEPTH_SIZE, out depth); System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil); int screen = (int)xplatui.GetField("ScreenNo",
Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples); System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers);
++buffers; // the above lines returns 0 - false and 1 - true.
int st;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
stereo = st != 0;
GraphicsMode gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples,
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, visual);
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, API.CreateColormap(display, root, visual, 0));
xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, visual);
xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
.SetValue(null, Functions.XCreateColormap(display, root, visual, 0));
}
Functions.XFree(visual);
return gfx; return gfx;
} }
} }

View file

@ -37,7 +37,6 @@ namespace OpenTK.Platform.X11
{ {
// Get available resolutions. Then, for each resolution get all // Get available resolutions. Then, for each resolution get all
// available rates. // available rates.
// TODO: Find a way to get all available depths, too.
// TODO: Global X11 lock. // TODO: Global X11 lock.
for (int screen = 0; screen < API.ScreenCount; screen++) for (int screen = 0; screen < API.ScreenCount; screen++)
{ {
@ -85,11 +84,10 @@ namespace OpenTK.Platform.X11
int current_resolution_index = Functions.XRRConfigCurrentConfiguration(screen_config, out current_rotation); int current_resolution_index = Functions.XRRConfigCurrentConfiguration(screen_config, out current_rotation);
DisplayDevice current_device = new DisplayDevice( DisplayDevice current_device = new DisplayDevice(
new DisplayResolution( new DisplayResolution(available_res[current_resolution_index].Width, available_res[current_resolution_index].Height,
available_res[current_resolution_index].Width, current_depth, current_refresh_rate),
available_res[current_resolution_index].Height, screen == Functions.XDefaultScreen(API.DefaultDisplay),
current_depth, current_refresh_rate), available_res);
screen == API.DefaultScreen, available_res);
deviceToScreen.Add(current_device, screen); deviceToScreen.Add(current_device, screen);
deviceToDefaultResolution.Add(current_device, current_resolution_index); deviceToDefaultResolution.Add(current_device, current_resolution_index);
@ -127,7 +125,7 @@ namespace OpenTK.Platform.X11
static float FindCurrentRefreshRate(int screen) static float FindCurrentRefreshRate(int screen)
{ {
IntPtr screen_config = Functions.XRRGetScreenInfo(API.DefaultDisplay, API.RootWindow); 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); short rate = Functions.XRRConfigCurrentRate(screen_config);