Opentk/Source/Examples/OpenTK/Test/Extensions.cs

250 lines
8.6 KiB
C#

#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.Text.RegularExpressions;
namespace Examples.WinForms
{
[Example("OpenGL Extensions", ExampleCategory.OpenTK, "Test", Documentation="Extensions")]
public partial class Extensions : Form
{
#region Fields
int supported_count, opengl_function_count; // Number of supported extensions.
SortedDictionary<Function, bool> functions = new SortedDictionary<Function, bool>();
#endregion
#region Constructors
public Extensions()
{
this.Font = SystemFonts.MessageBoxFont;
InitializeComponent();
Application.Idle += StartAsync;
// Workaround for missing Idle event on Mono/Windows.
if (Configuration.RunningOnMono && Configuration.RunningOnWindows)
Application.RaiseIdle(EventArgs.Empty);
}
#endregion
#region Private Members
// Creates a context and starts processing the GL class.
// The processing takes place in the background to avoid hanging the GUI.
void StartAsync(object sender, EventArgs e)
{
Application.Idle -= StartAsync;
// Create a context to load all GL entry points.
// The loading part is handled automatically by OpenTK.
using (INativeWindow window = new OpenTK.NativeWindow())
using (IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, window.WindowInfo, 3, 0, GraphicsContextFlags.Default))
{
window.ProcessEvents();
context.MakeCurrent(window.WindowInfo);
(context as IGraphicsContextInternal).LoadAll();
TextBoxVendor.Text = GL.GetString(StringName.Vendor);
TextBoxRenderer.Text = GL.GetString(StringName.Renderer);
TextBoxVersion.Text = GL.GetString(StringName.Version);
}
backgroundWorker1.RunWorkerAsync();
TextBoxSupport.Text = "processing... (please be patient)";
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Type delegates = typeof(GL).GetNestedType("Delegates", BindingFlags.NonPublic | BindingFlags.Static);
foreach (Function f in LoadFunctionsFromType(typeof(GL)))
{
FieldInfo @delegate = delegates.GetField(f.EntryPoint,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
// Only show a function as supported when all relevant overloads are supported.
if (!functions.ContainsKey(f))
functions.Add(f, @delegate != null && @delegate.GetValue(null) != null);
else
functions[f] &= @delegate != null && @delegate.GetValue(null) != null;
}
// Count supported functions using the delegates directly.
foreach (FieldInfo f in typeof(GL).GetNestedType("Delegates", BindingFlags.NonPublic)
.GetFields(BindingFlags.Static | BindingFlags.NonPublic))
{
if (f.GetValue(null) != null)
supported_count++;
opengl_function_count++;
}
}
// Recursively load all functions marked with [AutoGenerated] in the specified Type.
IEnumerable<Function> LoadFunctionsFromType(Type type)
{
foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
// Functions in GLHelper.cs are not autogenerated and should be skipped.
AutoGeneratedAttribute[] attr = (AutoGeneratedAttribute[])
method.GetCustomAttributes(typeof(AutoGeneratedAttribute), false);
if (attr.Length == 0)
continue;
string returnType = method.ReturnParameter.ToString();
List<string> args = new List<string>();
foreach (ParameterInfo item in method.GetParameters())
{
args.Add(item.ToString());
}
string argsStr = String.Join(", ", args.ToArray());
string fullMethodName = String.Format("{0} {1}({2})", returnType, method.Name, argsStr);
yield return new Function(fullMethodName, type.Name,
attr[0].EntryPoint, attr[0].Version, attr[0].Category);
}
foreach (Type nested_type in type.GetNestedTypes(BindingFlags.Public | BindingFlags.Static))
foreach (Function f in LoadFunctionsFromType(nested_type))
yield return f;
}
// Update the DataGridView with our findings.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
TextBoxSupport.Text = String.Format("{0} of {1} functions supported.",
supported_count, opengl_function_count);
foreach (Function f in functions.Keys)
{
dataGridView1.Rows.Add(functions[f], f.Name, f.Category, f.Version, f.Extension, f.EntryPoint);
int index = dataGridView1.Rows.Count - 1;
// Some simple coloring to make the GridView easier on the eyes.
// Supported functions are green, unsupported are redish.
dataGridView1.Rows[index].DefaultCellStyle.BackColor =
functions[f] ?
(index % 2 != 0 ? Color.FromArgb(128, 255, 192) : Color.FromArgb(192, 255, 192)) :
(index % 2 != 0 ? Color.FromArgb(255, 192, 160) : Color.FromArgb(255, 200, 160));
}
// Change the width of our Form to make every DataGridView column visible.
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
dataGridView1.Columns[1].Width = 450;
this.Size = dataGridView1.GetPreferredSize(new System.Drawing.Size(2000, Height));
}
#endregion
#region public static void Main()
/// <summary>
/// Entry point of this example.
/// </summary>
[STAThread]
public static void Main()
{
using (Extensions example = new Extensions())
{
Utilities.SetWindowTitle(example);
example.ShowDialog();
}
}
#endregion
}
#region class Function
// A simple class where we store information from OpenTK.Graphics.GL.
sealed class Function : IEquatable<Function>, IComparable<Function>
{
#region Fields
// We use these fields to distinguish between functions.
public readonly string Name;
public readonly string Category;
// These fields just provide some extra (cosmetic) information.
public readonly string EntryPoint;
public readonly string Version;
public readonly string Extension;
#endregion
#region Constructors
public Function(string name, string category, string entryPoint, string version, string extension)
{
Name = name;
Category = category == "GL" ? String.Empty : category;
EntryPoint = entryPoint;
Version = version;
Extension = extension;
}
#endregion
#region Public Members
public override bool Equals(object obj)
{
if (obj is Function)
return this.Equals((Function)obj);
return false;
}
public override int GetHashCode()
{
return Name.GetHashCode() ^ Category.GetHashCode();
}
#endregion
#region IEquatable<Function> Members
public bool Equals(Function other)
{
return
Category == other.Category &&
Name == other.Name;
}
#endregion
#region IComparable<Function> Members
public int CompareTo(Function other)
{
int order = Category.CompareTo(other.Category);
if (order == 0)
order = Name.CompareTo(other.Name);
return order;
}
#endregion
}
#endregion
}