From ef16998dca01edf44cbf21f890ca8b7093746c35 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Mon, 24 Mar 2008 13:12:02 +0000 Subject: [PATCH] Use one display connection for all X11 communication. Seems to fix (not 100%) the crash problems encountered. --- Source/OpenTK/GameWindow.cs | 2 +- Source/OpenTK/Graphics/DisplayDevice.cs | 14 ++- Source/OpenTK/Platform/X11/API.cs | 55 ++++++--- Source/OpenTK/Platform/X11/Functions.cs | 43 ++++++- Source/OpenTK/Platform/X11/X11GLControl.cs | 2 +- Source/OpenTK/Platform/X11/X11GLNative.cs | 26 ++--- Source/OpenTK/Platform/X11/X11GraphicsMode.cs | 110 +++++++++++------- .../Platform/X11/X11XrandrDisplayDevice.cs | 12 +- 8 files changed, 168 insertions(+), 96 deletions(-) diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs index 2d6765de..1b690c0c 100644 --- a/Source/OpenTK/GameWindow.cs +++ b/Source/OpenTK/GameWindow.cs @@ -2,7 +2,7 @@ /* Licensed under the MIT/X11 license. * 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. + * See license.txt for licensing details. */ #endregion diff --git a/Source/OpenTK/Graphics/DisplayDevice.cs b/Source/OpenTK/Graphics/DisplayDevice.cs index 2bdc6510..8e81dc7e 100644 --- a/Source/OpenTK/Graphics/DisplayDevice.cs +++ b/Source/OpenTK/Graphics/DisplayDevice.cs @@ -338,9 +338,9 @@ namespace OpenTK.Graphics { Form form = new Form(); form.ShowInTaskbar = false; - form.StartPosition = FormStartPosition.Manual; - form.FormBorderStyle = FormBorderStyle.None; + form.StartPosition = FormStartPosition.Manual; form.WindowState = FormWindowState.Maximized; + form.FormBorderStyle = FormBorderStyle.None; form.TopMost = true; form.BackColor = System.Drawing.Color.Black; @@ -353,9 +353,13 @@ namespace OpenTK.Graphics void MoveToStartPositions() { - //int count = 0; - //foreach (Screen s in Screen.AllScreens) - // forms[count++].Location = new System.Drawing.Point(s.Bounds.X, s.Bounds.Y); + int count = 0; + foreach (Screen s in Screen.AllScreens) + { + // 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 diff --git a/Source/OpenTK/Platform/X11/API.cs b/Source/OpenTK/Platform/X11/API.cs index 41a7ddec..b97b2272 100644 --- a/Source/OpenTK/Platform/X11/API.cs +++ b/Source/OpenTK/Platform/X11/API.cs @@ -8,7 +8,8 @@ using System; using System.Collections.Generic; using System.Text; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; +using System.Diagnostics; namespace OpenTK.Platform.X11 { @@ -38,7 +39,6 @@ namespace OpenTK.Platform.X11 using Rotation = System.UInt16; using Status = System.Int32; using SizeID = System.UInt16; - using System.Diagnostics; #endregion @@ -57,37 +57,56 @@ namespace OpenTK.Platform.X11 static int screenCount; internal static Display DefaultDisplay { get { return defaultDisplay; } } - internal static int DefaultScreen { get { return defaultScreen; } } - internal static Window RootWindow { get { return rootWindow; } } - internal static int ScreenCount { get { return screenCount; } } + //internal static int DefaultScreen { get { return defaultScreen; } } + //internal static Window RootWindow { get { return rootWindow; } } + internal static int ScreenCount { get { return screenCount; } } + + internal static object Lock = new object(); #endregion static API() { - //AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); - defaultDisplay = Functions.XOpenDisplay(IntPtr.Zero); - defaultScreen = Functions.XDefaultScreen(DefaultDisplay); - rootWindow = Functions.XRootWindow(DefaultDisplay, DefaultScreen); + AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); + + //using (System.Windows.Forms.Control c = new System.Windows.Forms.Control()) { } + //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); - Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}", - DefaultDisplay, DefaultScreen, RootWindow, ScreenCount); + //Debug.Print("Default Display: {0}, Default Screen: {1}, Default Root Window: {2}, Screen Count: {3}", + // DefaultDisplay, DefaultScreen, RootWindow, ScreenCount); + Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount); } 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 - [DllImport(_dll_name, EntryPoint = "XOpenDisplay")] - extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name); + //[DllImport(_dll_name, EntryPoint = "XOpenDisplay")] + //extern public static IntPtr OpenDisplay([MarshalAs(UnmanagedType.LPTStr)] string display_name); - [DllImport(_dll_name, EntryPoint = "XCloseDisplay")] - extern public static void CloseDisplay(Display display); + //[DllImport(_dll_name, EntryPoint = "XCloseDisplay")] + //extern public static void CloseDisplay(Display display); - [DllImport(_dll_name, EntryPoint = "XCreateColormap")] - extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc); + //[DllImport(_dll_name, EntryPoint = "XCreateColormap")] + //extern public static IntPtr CreateColormap(Display display, Window window, IntPtr visual, int alloc); #region Window handling diff --git a/Source/OpenTK/Platform/X11/Functions.cs b/Source/OpenTK/Platform/X11/Functions.cs index 3ea8ec2c..fdfdecd7 100644 --- a/Source/OpenTK/Platform/X11/Functions.cs +++ b/Source/OpenTK/Platform/X11/Functions.cs @@ -12,7 +12,36 @@ using System.Text; using System.Runtime.InteropServices; 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 { 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); [DllImport("libX11", EntryPoint = "XGetVisualInfo")] - static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, - out int nitems); - - + static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr 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); - } + } + + [DllImport("libX11")] + public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc); + } } diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs index dfab285e..4b0b1d70 100644 --- a/Source/OpenTK/Platform/X11/X11GLControl.cs +++ b/Source/OpenTK/Platform/X11/X11GLControl.cs @@ -39,7 +39,7 @@ namespace OpenTK.Platform.X11 xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) .SetValue(null, window.VisualInfo.visual); 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 --- diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 9c40db0b..33ccf0c7 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -1,6 +1,8 @@ #region --- License --- -/* Copyright (c) 2007 Stefanos Apostolopoulos - * See license.txt for license info +/* Licensed under the MIT/X11 license. + * 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 @@ -93,7 +95,7 @@ namespace OpenTK.Platform.X11 // 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. - 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) throw new Exception("Could not open connection to X"); window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; @@ -157,13 +159,11 @@ namespace OpenTK.Platform.X11 XSetWindowAttributes attributes = new XSetWindowAttributes(); attributes.background_pixel = IntPtr.Zero; attributes.border_pixel = IntPtr.Zero; - attributes.colormap = - API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); - window.EventMask = - EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | - EventMask.KeyReleaseMask | EventMask.KeyPressMask | - EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask | - EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; + attributes.colormap = Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0/*AllocNone*/); + window.EventMask = EventMask.StructureNotifyMask | EventMask.SubstructureNotifyMask | EventMask.ExposureMask | + EventMask.KeyReleaseMask | EventMask.KeyPressMask | + EventMask.PointerMotionMask | // Bad! EventMask.PointerMotionHintMask | + EventMask.ButtonPressMask | EventMask.ButtonReleaseMask; attributes.event_mask = (IntPtr)window.EventMask; uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | @@ -664,10 +664,10 @@ namespace OpenTK.Platform.X11 { if (window != null) { - if (window.WindowHandle != IntPtr.Zero) + if (window.WindowHandle != IntPtr.Zero) Functions.XDestroyWindow(window.Display, window.WindowHandle); - if (window.Display != IntPtr.Zero) - Functions.XCloseDisplay(window.Display); + //if (window.Display != IntPtr.Zero) + // Functions.XCloseDisplay(window.Display); window = null; } diff --git a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs index 66c40d31..cba9ceaa 100644 --- a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs +++ b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs @@ -25,7 +25,11 @@ namespace OpenTK.Platform.X11 public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) { - List visualAttributes = new List(); + GraphicsMode gfx; // The actual GraphicsMode that will be selected. + List visualAttributes = new List(); + IntPtr visual; + + Debug.Print("Bits per pixel: {0}", color.BitsPerPixel); if (color.BitsPerPixel > 0) { @@ -40,6 +44,8 @@ namespace OpenTK.Platform.X11 visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); visualAttributes.Add(color.Alpha); } + + Debug.Print("Depth: {0}", depth); if (depth > 0) { @@ -71,56 +77,70 @@ namespace OpenTK.Platform.X11 if (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. - // 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); + visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray()); - 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) - throw new GraphicsContextException("Requested GraphicsMode not available."); + // See what we *really* got: + 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)); - - // See what we *really* got: - 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; - - 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)); + gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples, + new ColorFormat(ar, ag, ab, aa), buffers, stereo); + + //Functions.XCloseDisplay(display); + } + + // Prepare Windows.Forms for creating OpenGL drawables. + lock (API.Lock) + { + 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); + + 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; } } diff --git a/Source/OpenTK/Platform/X11/X11XrandrDisplayDevice.cs b/Source/OpenTK/Platform/X11/X11XrandrDisplayDevice.cs index f44fbc6a..7ff9eca4 100644 --- a/Source/OpenTK/Platform/X11/X11XrandrDisplayDevice.cs +++ b/Source/OpenTK/Platform/X11/X11XrandrDisplayDevice.cs @@ -37,7 +37,6 @@ namespace OpenTK.Platform.X11 { // Get available resolutions. Then, for each resolution get all // available rates. - // TODO: Find a way to get all available depths, too. // TODO: Global X11 lock. 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); DisplayDevice current_device = new DisplayDevice( - new DisplayResolution( - available_res[current_resolution_index].Width, - available_res[current_resolution_index].Height, - current_depth, current_refresh_rate), - screen == API.DefaultScreen, available_res); + new DisplayResolution(available_res[current_resolution_index].Width, available_res[current_resolution_index].Height, + current_depth, current_refresh_rate), + screen == Functions.XDefaultScreen(API.DefaultDisplay), + available_res); deviceToScreen.Add(current_device, screen); deviceToDefaultResolution.Add(current_device, current_resolution_index); @@ -127,7 +125,7 @@ namespace OpenTK.Platform.X11 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; int size = Functions.XRRConfigCurrentConfiguration(screen_config, out rotation); short rate = Functions.XRRConfigCurrentRate(screen_config);