From f031e34ecfd1fe0ee0ce8ae6e1568214532ce781 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Fri, 24 Jul 2009 21:13:46 +0000 Subject: [PATCH] Initial implementation. --- Source/OpenTK/Platform/Egl/EglContext.cs | 208 ++++++++++++++---- Source/OpenTK/Platform/Egl/EglGraphicsMode.cs | 46 ++++ Source/OpenTK/Platform/Egl/EglWindowInfo.cs | 63 ++++++ 3 files changed, 277 insertions(+), 40 deletions(-) create mode 100644 Source/OpenTK/Platform/Egl/EglGraphicsMode.cs create mode 100644 Source/OpenTK/Platform/Egl/EglWindowInfo.cs diff --git a/Source/OpenTK/Platform/Egl/EglContext.cs b/Source/OpenTK/Platform/Egl/EglContext.cs index 2f6eab12..af9891aa 100644 --- a/Source/OpenTK/Platform/Egl/EglContext.cs +++ b/Source/OpenTK/Platform/Egl/EglContext.cs @@ -1,40 +1,168 @@ -#region License -// -// The Open Toolkit Library License -// -// Copyright (c) 2006 - 2009 the Open Toolkit library. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -#endregion - -using System; - -using OpenTK.Graphics; - -namespace OpenTK.Platform.Egl -{ - public class EglContext /*: IGraphicsContext*/ - { - public EglContext() - { - } - } -} +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2009 the Open Toolkit library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; + +using OpenTK.Graphics; +using System.Diagnostics; + +namespace OpenTK.Platform.Egl +{ + class EglContext : IGraphicsContext + { + #region Fields + + EglWindowInfo window; + EGLContext context; + GraphicsMode mode; + bool vsync = true; // Default vsync value is defined as 1 (true) in EGL. + bool disposed = false; + + #endregion + + #region Constructors + + public EglContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + { + if (mode == null) + throw new ArgumentNullException("mode"); + if (window == null) + throw new ArgumentNullException("window"); + + EglContext shared = (EglContext)sharedContext; + + Egl.Initialize(window.Display, out major, out minor); + + EGLConfig config = new EGLConfig(mode.Index); + + if (window.Surface.Handle == EGLSurface.None.Handle) + window.CreateWindowSurface(config); + + context = Egl.CreateContext(window.Display, config, shared.context, null); + MakeCurrent(window); + } + + #endregion + + #region IGraphicsContext Members + + public void SwapBuffers() + { + Egl.SwapBuffers(window.Display, window.Surface); + } + + public void MakeCurrent(IWindowInfo window) + { + EglWindowInfo egl = (EglWindowInfo)window; + Egl.MakeCurrent(egl.Display, egl.Surface, egl.Surface, context); + this.window = egl; + } + + public bool IsCurrent + { + get { return Egl.GetCurrentContext().Handle == context.Handle; } + } + + public event DestroyEvent Destroy; + + public bool VSync + { + get + { + // Egl.GetSwapInterval does not exist, so store and return the current interval. + // The default interval is defined as 1 (true). + return vsync; + } + set + { + if (Egl.SwapInterval(window.Display, value ? 1 : 0)) + vsync = value; + else + Debug.Print("[Warning] Egl.SwapInterval({0}, {1}) failed.", window.Display, value); + } + } + + public void Update(IWindowInfo window) + { + // Do nothing. + } + + public GraphicsMode GraphicsMode + { + get { return mode; } + } + + // Todo: implement this! + public bool ErrorChecking + { + get + { + return false; + } + set + { + } + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // Todo: cross-reference the specs. What should happen if the context is destroyed from a different + // thread? + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + Egl.MakeCurrent(window.Display, window.Surface, window.Surface, EGLContext.None); + Egl.DestroyContext(window.Display, context); + } + else + { + Debug.Print("[Warning] {0}:{1} was not disposed.", this.GetType().Name, context.Handle); + } + disposed = true; + } + } + + ~EglContext() + { + Dispose(false); + } + + #endregion + } +} diff --git a/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs b/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs new file mode 100644 index 00000000..190c8d22 --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglGraphicsMode.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenTK.Graphics; + +namespace OpenTK.Platform.Egl +{ + class EglGraphicsMode : IGraphicsMode + { + #region IGraphicsMode Members + + public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) + { + EGLConfig[] configs = new EGLConfig[1]; + int[] attribList = new int[] { Egl.SURFACE_TYPE, Egl.WINDOW_BIT, Egl.RED_SIZE, color.Red, Egl.GREEN_SIZE, color.Green, Egl.BLUE_SIZE, color.Blue, Egl.ALPHA_SIZE, color.Alpha, Egl.DEPTH_SIZE, depth > 0 ? depth : Egl.DONT_CARE, Egl.STENCIL_SIZE, stencil > 0 ? stencil : Egl.DONT_CARE, Egl.SAMPLE_BUFFERS, samples > 0 ? 1 : 0, Egl.SAMPLES, samples > 0 ? samples : 0, Egl.NONE, Egl.NONE }; + + // Todo: what if we don't wish to use the default display? + EGLDisplay display = Egl.GetDisplay(EGLNativeDisplayType.Default); + + int num_configs; + Egl.GetConfigs(display, configs, configs.Length, out num_configs); + if (num_configs == 0) + throw new NotSupportedException("The requested GraphicsMode is not supported."); + + // See what we really got + EGLConfig active_config = configs[0]; + int r, g, b, a; + Egl.GetConfigAttrib(display, active_config, Egl.RED_SIZE, out r); + Egl.GetConfigAttrib(display, active_config, Egl.GREEN_SIZE, out g); + Egl.GetConfigAttrib(display, active_config, Egl.BLUE_SIZE, out b); + Egl.GetConfigAttrib(display, active_config, Egl.ALPHA_SIZE, out a); + int d, s; + Egl.GetConfigAttrib(display, active_config, Egl.DEPTH_SIZE, out d); + Egl.GetConfigAttrib(display, active_config, Egl.STENCIL_SIZE, out s); + Egl.GetConfigAttrib(display, active_config, Egl.BLUE_SIZE, out b); + Egl.GetConfigAttrib(display, active_config, Egl.ALPHA_SIZE, out a); + int sample_buffers; + Egl.GetConfigAttrib(display, active_config, Egl.SAMPLES, out sample_buffers); + Egl.GetConfigAttrib(display, active_config, Egl.SAMPLES, out samples); + + return new GraphicsMode(active_config.Handle.Value, new ColorFormat(r, g, b, a), depth, stencil, sample_buffers > 0 ? samples : 0, 0, 2, false); + } + + #endregion + } +} diff --git a/Source/OpenTK/Platform/Egl/EglWindowInfo.cs b/Source/OpenTK/Platform/Egl/EglWindowInfo.cs new file mode 100644 index 00000000..25bf3103 --- /dev/null +++ b/Source/OpenTK/Platform/Egl/EglWindowInfo.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Platform.Egl +{ + // Holds information about an EGL window. + class EglWindowInfo : IWindowInfo + { + #region Fields + + IntPtr handle; + EGLDisplay display; + EGLSurface surface; + + #endregion + + #region Constructiors + + public EglWindowInfo(IntPtr handle, EGLDisplay display, EGLSurface surface) + { + Handle = handle; + Display = display; + Surface = surface; + } + + #endregion + + #region Public Members + + public IntPtr Handle { get { return handle; } private set { handle = value; } } + + public EGLDisplay Display { get { return display; } private set { display = value; } } + + public EGLSurface Surface { get { return surface; } private set { surface = value; } } + + public void CreateWindowSurface(EGLConfig config) + { + Surface = Egl.CreateWindowSurface(Display, config, Handle, null); + } + + //public void CreatePixmapSurface(EGLConfig config) + //{ + // Surface = Egl.CreatePixmapSurface(Display, config, Handle, null); + //} + + //public void CreatePbufferSurface(EGLConfig config) + //{ + // Surface = Egl.CreatePbufferSurface(Display, config, null); + //} + + #endregion + + #region IDisposable Members + + public void Dispose() + { + throw new NotImplementedException(); + } + + #endregion + } +}