public static ExtractedFeatureSet Create(Registry registry, IEnumerable <FeatureComponent> src_set) { var set = new ExtractedFeatureSet(); foreach (var feature in src_set) { if (feature is CommandFeature cmd) { set.commands.Add(registry.Commands.SelectMany(c => c.Items).Single(c => c.Prototype.Name == cmd.Name)); } else if (feature is EnumFeature en) { var empty = new Enum[0]; set.enums.Add(registry.Enums.SelectMany(e => e.Items ?? empty).Single(e => e.Name == en.Name)); } } return(set); }
static int Main(string[] args) { string registry_file = args[0]; string result_file = args[1]; string api_version = args[2]; string[] extensions = args.Skip(3).ToArray(); string profile = "core"; // var serializer = new XmlSerializer(typeof(Registry)); Registry registry; using (var sr = new StreamReader(registry_file)) { registry = (Registry)serializer.Deserialize(sr); } var target_feature = registry.Features.First(f => f.Name == api_version); var api = target_feature.API; var required_features = registry.Features .Where(f => f.API == target_feature.API) .Where(f => f.Number.CompareTo(target_feature.Number) <= 0) .OrderBy(f => f.Number) .ToArray(); var wanted_extensions = registry.Extensions .Where(e => extensions.Contains(e.Name)) .ToArray(); if (wanted_extensions.Length != extensions.Length) { Console.Error.WriteLine("The following extensions could not be found:"); foreach (var ext in extensions.Where(e => !wanted_extensions.Any(e2 => e2.Name == e))) { Console.Error.WriteLine(" {0}", ext); } return(1); } foreach (var ext in wanted_extensions) { if (!ext.IsCompatibleTo(target_feature)) { Console.Error.WriteLine("{0} is not compatible to {1}", ext.Name, api_version); return(1); } if (ext.Removes != null) { Console.Error.WriteLine("{0} would remove features. This is not supported yet.", ext.Name); return(1); } } var final_feature_set = new HashSet <FeatureComponent>(); foreach (var feat in required_features) { var empty = new FeatureComponent[0]; foreach (var item in feat.GetRemovedComponents(api, profile)) { final_feature_set.Remove(item); } foreach (var item in feat.GetRequiredComponents(api, profile)) { final_feature_set.Add(item); } } var gl_set = ExtractedFeatureSet.Create(registry, final_feature_set); var gl_extensions = new List <Tuple <string, ExtractedFeatureSet> >(); foreach (var ext in wanted_extensions) { var empty = new FeatureComponent[0]; gl_extensions.Add(Tuple.Create( ext.Name, ExtractedFeatureSet.Create(registry, ext.GetRequiredComponents(api, profile)) )); } Console.WriteLine("Final API has {0} commands and {1} enums types.", gl_set.commands.Count, gl_set.enums.Count ); foreach (var ext in wanted_extensions) { Console.WriteLine(" {0}", ext.Name); } var all_commands = gl_set.commands.Concat(gl_extensions.SelectMany(c => c.Item2.commands)); using (var stream = new StreamWriter(result_file, false, Encoding.UTF8)) { stream.WriteLine("const std = @import(\"std\");"); stream.WriteLine("const log = std.log.scoped(.OpenGL);"); stream.WriteLine(); stream.WriteLine(preamble); stream.WriteLine(); WriteConstants(stream, gl_set.enums); stream.WriteLine(); WriteCommands(stream, gl_set.commands); stream.WriteLine("// Extensions:"); stream.WriteLine(); foreach (var ext in gl_extensions) { stream.WriteLine("pub const {0} = struct {{", ext.Item1); WriteConstants(stream, ext.Item2.enums); stream.WriteLine(); WriteCommands(stream, ext.Item2.commands); stream.WriteLine(); WriteLoader(stream, ext.Item2.commands); stream.WriteLine("};"); stream.WriteLine(); } stream.WriteLine("// Loader API:"); WriteLoader(stream, gl_set.commands); stream.WriteLine(); stream.WriteLine("const function_signatures = struct {"); foreach (var cmd in all_commands) { stream.WriteLine(" const {0} = {1};", cmd.Prototype.Name, cmd.GetSignature(false)); } stream.WriteLine("};"); stream.WriteLine(); stream.WriteLine("const function_pointers = struct {"); foreach (var cmd in all_commands) { stream.WriteLine(" var {0}: ?function_signatures.{0} = null;", cmd.Prototype.Name); } stream.WriteLine("};"); stream.WriteLine(); stream.WriteLine("test \"\" {"); stream.WriteLine(" _ = load;"); stream.WriteLine(" @setEvalBranchQuota(100_000); // Yes, this is necessary. OpenGL gets quite large!"); stream.WriteLine(" std.testing.refAllDecls(@This());"); stream.WriteLine("}"); } return(0); }