using System; using System.Runtime.InteropServices; using FSpot.Widgets; using Tao.OpenGl; namespace GdkGlx { public enum GlxAttribute { None = 0, UseGL = 1, BufferSize = 2, Level = 3, Rgba = 4, DoubleBuffer = 5, Stereo = 6, AuxBuffers = 7, RedSize = 8, GreenSize = 9, BlueSize = 10, AlphaSize = 11, DepthSize = 12, StencilSize = 13, AccumRedSize = 14, AccumGreenSize = 15, AccumBlueSize = 16, AccumAlphaSize = 17 } public class GlxException : System.Exception { public GlxException (string text) : base (text) { } public GlxException (string text, Exception e) : base (text, e) { } } public class Context { private HandleRef handle; private Gdk.Visual visual; [DllImport("X11")] static extern void XFree (IntPtr handle); [DllImport("GL")] static extern IntPtr glXCreateContext (IntPtr display, IntPtr visual_info, HandleRef share_list, bool direct); [DllImport("GL")] static extern IntPtr glXChooseVisual (IntPtr display, int screen, int [] attr); [DllImport("GL")] static extern void glXDestroyContext (IntPtr display, HandleRef ctx); [DllImport("GL")] static extern bool glXMakeCurrent (IntPtr display, uint xdrawable, HandleRef ctx); [DllImport("GL")] static extern void glXSwapBuffers (IntPtr display, uint drawable); public HandleRef Handle { get { return handle; } } public Context (Gdk.Screen screen, int [] attr) : this (screen, null, attr) { } [StructLayout(LayoutKind.Sequential)] private struct XVisualInfo { public IntPtr visual; public uint visualid; public int screen; public int depth; public int c_class; public uint red_mask; public uint blue_mask; public uint green_mask; public int colormap_size; public int bits_per_rgb; } #if false public Gdk.Colormap GetColormap (Gdk.Screen screen, ) { DrawableFormat template = new DrawableFormat (); template.Color = new ColorFormat (); FormatMask mask = FormatMask.None; int num = screen.Number; IntPtr dformat = GlitzAPI.glitz_glx_find_window_format (GdkUtils.GetXDisplay (screen.Display), num, mask, ref template, 0); visual_info = GlitzAPI.glitz_glx_get_visual_info_from_format (dpy, scr, dformat); Gdk.Visual visual = new Gdk.Visual (gdkx_visual_get (XVisualIDFromVisual (vinfo))); new Gdk.Colormap (visual, true); */ } #endif public Gdk.Colormap GetColormap () { return new Gdk.Colormap (visual, false); } public Context (Gdk.Screen screen, Context share_list, int [] attr) { IntPtr xdisplay = GdkUtils.GetXDisplay (screen.Display); IntPtr visual_info = IntPtr.Zero; // Be careful about the first glx call and handle the exception // with more grace. try { visual_info = glXChooseVisual (xdisplay, screen.Number, attr); } catch (DllNotFoundException e) { throw new GlxException ("Unable to find OpenGL libarary", e); } catch (EntryPointNotFoundException enf) { throw new GlxException ("Unable to find Glx entry point", enf); } if (visual_info == IntPtr.Zero) throw new GlxException ("Unable to find matching visual"); XVisualInfo xinfo = (XVisualInfo) Marshal.PtrToStructure (visual_info, typeof (XVisualInfo)); HandleRef share = share_list != null ? share_list.Handle : new HandleRef (null, IntPtr.Zero); IntPtr tmp = glXCreateContext (xdisplay, visual_info, share, true); if (tmp == IntPtr.Zero) throw new GlxException ("Unable to create context"); handle = new HandleRef (this, tmp); visual = GdkUtils.LookupVisual (screen, xinfo.visualid); if (visual_info != IntPtr.Zero) XFree (visual_info); } public void Destroy () { glXDestroyContext (GdkUtils.GetXDisplay (visual.Screen.Display), Handle); } public bool MakeCurrent (Gdk.Drawable drawable) { return glXMakeCurrent (GdkUtils.GetXDisplay (drawable.Display), GdkUtils.GetXid (drawable), Handle); } public void SwapBuffers (Gdk.Drawable drawable) { glXSwapBuffers (GdkUtils.GetXDisplay (drawable.Display), GdkUtils.GetXid (drawable)); } } }