GenerateGLAPIWrapper.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. /*
  2. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Array.h>
  7. #include <AK/DeprecatedString.h>
  8. #include <AK/JsonObject.h>
  9. #include <AK/NumericLimits.h>
  10. #include <AK/Optional.h>
  11. #include <AK/SourceGenerator.h>
  12. #include <AK/StringBuilder.h>
  13. #include <AK/StringView.h>
  14. #include <AK/Vector.h>
  15. #include <LibCore/ArgsParser.h>
  16. #include <LibCore/File.h>
  17. #include <LibCore/Stream.h>
  18. #include <LibMain/Main.h>
  19. struct ArgumentDefinition {
  20. Optional<DeprecatedString> name;
  21. Optional<DeprecatedString> cpp_type;
  22. DeprecatedString expression;
  23. Optional<DeprecatedString> cast_to;
  24. };
  25. struct FunctionDefinition {
  26. DeprecatedString name;
  27. DeprecatedString return_type;
  28. Vector<ArgumentDefinition> arguments;
  29. DeprecatedString implementation;
  30. bool unimplemented;
  31. DeprecatedString variant_gl_type;
  32. };
  33. struct VariantType {
  34. DeprecatedString encoded_type;
  35. Optional<DeprecatedString> implementation;
  36. bool unimplemented;
  37. };
  38. struct Variants {
  39. Vector<DeprecatedString> api_suffixes { "" };
  40. Vector<u32> argument_counts { NumericLimits<u32>::max() };
  41. Vector<DeprecatedString> argument_defaults { "" };
  42. bool convert_range { false };
  43. Vector<VariantType> types {
  44. {
  45. .encoded_type = "",
  46. .implementation = Optional<DeprecatedString> {},
  47. .unimplemented = false,
  48. }
  49. };
  50. DeprecatedString pointer_argument { "" };
  51. };
  52. struct EncodedTypeEntry {
  53. StringView encoded_type;
  54. StringView cpp_type;
  55. StringView gl_type;
  56. };
  57. // clang-format off
  58. constexpr static Array<EncodedTypeEntry, 9> type_definitions = {
  59. EncodedTypeEntry { "b"sv, "GLbyte"sv, "GL_BYTE"sv },
  60. EncodedTypeEntry { "d"sv, "GLdouble"sv, "GL_DOUBLE"sv },
  61. EncodedTypeEntry { "f"sv, "GLfloat"sv, "GL_FLOAT"sv },
  62. EncodedTypeEntry { "i"sv, "GLint"sv, "GL_INT"sv },
  63. EncodedTypeEntry { "s"sv, "GLshort"sv, "GL_SHORT"sv },
  64. EncodedTypeEntry { "ub"sv, "GLubyte"sv, "GL_UNSIGNED_BYTE"sv },
  65. EncodedTypeEntry { "ui"sv, "GLuint"sv, "GL_UNSIGNED_INT"sv },
  66. EncodedTypeEntry { "us"sv, "GLushort"sv, "GL_UNSIGNED_SHORT"sv },
  67. EncodedTypeEntry { "x"sv, "GLfixed"sv, "GL_INT"sv },
  68. };
  69. // clang-format on
  70. struct EncodedType {
  71. EncodedTypeEntry type_entry;
  72. DeprecatedString cpp_type;
  73. DeprecatedString function_name_suffix;
  74. bool is_pointer;
  75. bool is_const_pointer;
  76. };
  77. Vector<DeprecatedString> get_name_list(Optional<JsonValue const&> name_definition)
  78. {
  79. if (!name_definition.has_value() || name_definition->is_null())
  80. return {};
  81. Vector<DeprecatedString, 1> names;
  82. if (name_definition->is_string()) {
  83. names.append(name_definition->as_string());
  84. } else if (name_definition->is_array()) {
  85. name_definition->as_array().for_each([&names](auto& value) {
  86. VERIFY(value.is_string());
  87. names.append(value.as_string());
  88. });
  89. } else {
  90. VERIFY_NOT_REACHED();
  91. }
  92. return names;
  93. }
  94. Optional<EncodedType> get_encoded_type(DeprecatedString encoded_type)
  95. {
  96. bool is_const_pointer = !encoded_type.ends_with('!');
  97. if (!is_const_pointer)
  98. encoded_type = encoded_type.substring_view(0, encoded_type.length() - 1);
  99. DeprecatedString function_name_suffix = encoded_type;
  100. bool is_pointer = encoded_type.ends_with('v');
  101. if (is_pointer)
  102. encoded_type = encoded_type.substring_view(0, encoded_type.length() - 1);
  103. VERIFY(is_const_pointer || is_pointer);
  104. Optional<EncodedTypeEntry> type_definition;
  105. for (size_t i = 0; i < type_definitions.size(); ++i) {
  106. if (type_definitions[i].encoded_type == encoded_type) {
  107. type_definition = type_definitions[i];
  108. break;
  109. }
  110. }
  111. if (!type_definition.has_value())
  112. return {};
  113. return EncodedType {
  114. .type_entry = type_definition.value(),
  115. .cpp_type = DeprecatedString::formatted(
  116. "{}{}{}",
  117. type_definition->cpp_type,
  118. is_pointer && is_const_pointer ? " const" : "",
  119. is_pointer ? "*" : ""),
  120. .function_name_suffix = function_name_suffix,
  121. .is_pointer = is_pointer,
  122. .is_const_pointer = is_const_pointer,
  123. };
  124. }
  125. DeprecatedString wrap_expression_in_range_conversion(DeprecatedString source_type, DeprecatedString target_type, DeprecatedString expression)
  126. {
  127. VERIFY(target_type == "GLfloat" || target_type == "GLdouble");
  128. // No range conversion required
  129. if (source_type == target_type || source_type == "GLdouble")
  130. return expression;
  131. if (source_type == "GLbyte")
  132. return DeprecatedString::formatted("({} + 128.) / 127.5 - 1.", expression);
  133. else if (source_type == "GLfloat")
  134. return DeprecatedString::formatted("static_cast<GLdouble>({})", expression);
  135. else if (source_type == "GLint")
  136. return DeprecatedString::formatted("({} + 2147483648.) / 2147483647.5 - 1.", expression);
  137. else if (source_type == "GLshort")
  138. return DeprecatedString::formatted("({} + 32768.) / 32767.5 - 1.", expression);
  139. else if (source_type == "GLubyte")
  140. return DeprecatedString::formatted("{} / 255.", expression);
  141. else if (source_type == "GLuint")
  142. return DeprecatedString::formatted("{} / 4294967296.", expression);
  143. else if (source_type == "GLushort")
  144. return DeprecatedString::formatted("{} / 65536.", expression);
  145. VERIFY_NOT_REACHED();
  146. }
  147. Variants read_variants_settings(JsonObject const& variants_obj)
  148. {
  149. Variants variants;
  150. if (variants_obj.has_array("argument_counts"sv)) {
  151. variants.argument_counts.clear_with_capacity();
  152. variants_obj.get_array("argument_counts"sv)->for_each([&](auto const& argument_count_value) {
  153. variants.argument_counts.append(argument_count_value.to_u32());
  154. });
  155. }
  156. if (variants_obj.has_array("argument_defaults"sv)) {
  157. variants.argument_defaults.clear_with_capacity();
  158. variants_obj.get_array("argument_defaults"sv)->for_each([&](auto const& argument_default_value) {
  159. variants.argument_defaults.append(argument_default_value.as_string());
  160. });
  161. }
  162. if (variants_obj.has_bool("convert_range"sv)) {
  163. variants.convert_range = variants_obj.get_bool("convert_range"sv).value();
  164. }
  165. if (variants_obj.has_array("api_suffixes"sv)) {
  166. variants.api_suffixes.clear_with_capacity();
  167. variants_obj.get_array("api_suffixes"sv)->for_each([&](auto const& suffix_value) {
  168. variants.api_suffixes.append(suffix_value.as_string());
  169. });
  170. }
  171. if (variants_obj.has_string("pointer_argument"sv)) {
  172. variants.pointer_argument = variants_obj.get_deprecated_string("pointer_argument"sv).value();
  173. }
  174. if (variants_obj.has_object("types"sv)) {
  175. variants.types.clear_with_capacity();
  176. variants_obj.get_object("types"sv)->for_each_member([&](auto const& key, auto const& type_value) {
  177. auto const& type = type_value.as_object();
  178. variants.types.append(VariantType {
  179. .encoded_type = key,
  180. .implementation = type.get_deprecated_string("implementation"sv),
  181. .unimplemented = type.get_bool("unimplemented"sv).value_or(false),
  182. });
  183. });
  184. }
  185. return variants;
  186. }
  187. Vector<ArgumentDefinition> copy_arguments_for_variant(Vector<ArgumentDefinition> arguments, Variants variants,
  188. u32 argument_count, EncodedType encoded_type)
  189. {
  190. Vector<ArgumentDefinition> variant_arguments = arguments;
  191. auto base_cpp_type = encoded_type.type_entry.cpp_type;
  192. size_t variadic_index = 0;
  193. for (size_t i = 0; i < variant_arguments.size(); ++i) {
  194. // Skip arguments with a fixed type
  195. if (variant_arguments[i].cpp_type.has_value())
  196. continue;
  197. variant_arguments[i].cpp_type = encoded_type.cpp_type;
  198. auto cast_to = variant_arguments[i].cast_to;
  199. // Pointer argument
  200. if (encoded_type.is_pointer) {
  201. variant_arguments[i].name = (variadic_index == 0) ? variants.pointer_argument : Optional<DeprecatedString> {};
  202. if (variadic_index >= argument_count) {
  203. // If this variable argument is past the argument count, fall back to the defaults
  204. variant_arguments[i].expression = variants.argument_defaults[variadic_index];
  205. variant_arguments[i].cast_to = Optional<DeprecatedString> {};
  206. } else if (argument_count == 1 && variants.argument_counts.size() == 1) {
  207. // Otherwise, if the pointer is the only variadic argument, pass it through unchanged
  208. variant_arguments[i].cast_to = Optional<DeprecatedString> {};
  209. } else {
  210. // Otherwise, index into the pointer argument
  211. auto indexed_expression = DeprecatedString::formatted("{}[{}]", variants.pointer_argument, variadic_index);
  212. if (variants.convert_range && cast_to.has_value())
  213. indexed_expression = wrap_expression_in_range_conversion(base_cpp_type, cast_to.value(), indexed_expression);
  214. variant_arguments[i].expression = indexed_expression;
  215. }
  216. } else {
  217. // Regular argument
  218. if (variadic_index >= argument_count) {
  219. // If the variable argument is past the argument count, fall back to the defaults
  220. variant_arguments[i].name = Optional<DeprecatedString> {};
  221. variant_arguments[i].expression = variants.argument_defaults[variadic_index];
  222. variant_arguments[i].cast_to = Optional<DeprecatedString> {};
  223. } else if (variants.convert_range && cast_to.has_value()) {
  224. // Otherwise, if we need to convert the input values, wrap the expression in a range conversion
  225. variant_arguments[i].expression = wrap_expression_in_range_conversion(
  226. base_cpp_type,
  227. cast_to.value(),
  228. variant_arguments[i].expression);
  229. }
  230. }
  231. // Determine if we can skip casting to the target type
  232. if (cast_to == base_cpp_type || (variants.convert_range && cast_to == "GLdouble"))
  233. variant_arguments[i].cast_to = Optional<DeprecatedString> {};
  234. variadic_index++;
  235. }
  236. return variant_arguments;
  237. }
  238. Vector<FunctionDefinition> create_function_definitions(DeprecatedString function_name, JsonObject const& function_definition)
  239. {
  240. // A single function definition can expand to multiple generated functions by way of:
  241. // - differing API suffices (ARB, EXT, etc.);
  242. // - differing argument counts;
  243. // - differing argument types.
  244. // These can all be combined.
  245. // Parse base argument definitions first; these may later be modified by variants
  246. Vector<ArgumentDefinition> argument_definitions;
  247. JsonArray const& arguments = function_definition.get_array("arguments"sv).value_or(JsonArray {});
  248. arguments.for_each([&argument_definitions](auto const& argument_value) {
  249. VERIFY(argument_value.is_object());
  250. auto const& argument = argument_value.as_object();
  251. auto type = argument.get_deprecated_string("type"sv);
  252. auto argument_names = get_name_list(argument.get("name"sv));
  253. auto expression = argument.get_deprecated_string("expression"sv).value_or("@argument_name@");
  254. auto cast_to = argument.get_deprecated_string("cast_to"sv);
  255. // Add an empty dummy name when all we have is an expression
  256. if (argument_names.is_empty() && !expression.is_empty())
  257. argument_names.append("");
  258. for (auto const& argument_name : argument_names) {
  259. argument_definitions.append({ .name = argument_name.is_empty() ? Optional<DeprecatedString> {} : argument_name,
  260. .cpp_type = type,
  261. .expression = expression,
  262. .cast_to = cast_to });
  263. }
  264. });
  265. // Create functions for each name and/or variant
  266. Vector<FunctionDefinition> functions;
  267. auto return_type = function_definition.get_deprecated_string("return_type"sv).value_or("void");
  268. auto function_implementation = function_definition.get_deprecated_string("implementation"sv).value_or(function_name.to_snakecase());
  269. auto function_unimplemented = function_definition.get_bool("unimplemented"sv).value_or(false);
  270. if (!function_definition.has("variants"sv)) {
  271. functions.append({
  272. .name = function_name,
  273. .return_type = return_type,
  274. .arguments = argument_definitions,
  275. .implementation = function_implementation,
  276. .unimplemented = function_unimplemented,
  277. .variant_gl_type = "",
  278. });
  279. return functions;
  280. }
  281. // Read variants settings for this function
  282. auto variants_obj = function_definition.get_object("variants"sv).value();
  283. auto variants = read_variants_settings(variants_obj);
  284. for (auto argument_count : variants.argument_counts) {
  285. for (auto const& variant_type : variants.types) {
  286. auto encoded_type = get_encoded_type(variant_type.encoded_type);
  287. auto variant_arguments = encoded_type.has_value()
  288. ? copy_arguments_for_variant(argument_definitions, variants, argument_count, encoded_type.value())
  289. : argument_definitions;
  290. auto variant_type_implementation = variant_type.implementation.has_value()
  291. ? variant_type.implementation.value()
  292. : function_implementation;
  293. for (auto const& api_suffix : variants.api_suffixes) {
  294. functions.append({
  295. .name = DeprecatedString::formatted(
  296. "{}{}{}{}",
  297. function_name,
  298. variants.argument_counts.size() > 1 ? DeprecatedString::formatted("{}", argument_count) : "",
  299. encoded_type.has_value() && variants.types.size() > 1 ? encoded_type->function_name_suffix : "",
  300. api_suffix),
  301. .return_type = return_type,
  302. .arguments = variant_arguments,
  303. .implementation = variant_type_implementation,
  304. .unimplemented = variant_type.unimplemented || function_unimplemented,
  305. .variant_gl_type = encoded_type.has_value() ? encoded_type->type_entry.gl_type : ""sv,
  306. });
  307. }
  308. }
  309. }
  310. return functions;
  311. }
  312. ErrorOr<void> generate_header_file(JsonObject& api_data, Core::File& file)
  313. {
  314. StringBuilder builder;
  315. SourceGenerator generator { builder };
  316. generator.appendln("#pragma once");
  317. generator.append("\n");
  318. generator.appendln("#include <LibGL/GL/glplatform.h>");
  319. generator.append("\n");
  320. generator.appendln("#ifdef __cplusplus");
  321. generator.appendln("extern \"C\" {");
  322. generator.appendln("#endif");
  323. generator.append("\n");
  324. api_data.for_each_member([&](auto& function_name, auto& value) {
  325. VERIFY(value.is_object());
  326. auto const& function = value.as_object();
  327. auto function_definitions = create_function_definitions(function_name, function);
  328. for (auto const& function_definition : function_definitions) {
  329. auto function_generator = generator.fork();
  330. function_generator.set("name", function_definition.name);
  331. function_generator.set("return_type", function_definition.return_type);
  332. function_generator.append("GLAPI @return_type@ gl@name@(");
  333. bool first = true;
  334. for (auto const& argument_definition : function_definition.arguments) {
  335. if (!argument_definition.name.has_value() || !argument_definition.cpp_type.has_value())
  336. continue;
  337. auto argument_generator = function_generator.fork();
  338. argument_generator.set("argument_type", argument_definition.cpp_type.value());
  339. argument_generator.set("argument_name", argument_definition.name.value());
  340. if (!first)
  341. argument_generator.append(", ");
  342. first = false;
  343. argument_generator.append("@argument_type@ @argument_name@");
  344. }
  345. function_generator.appendln(");");
  346. }
  347. });
  348. generator.appendln("#ifdef __cplusplus");
  349. generator.appendln("}");
  350. generator.appendln("#endif");
  351. TRY(file.write(generator.as_string_view().bytes()));
  352. return {};
  353. }
  354. ErrorOr<void> generate_implementation_file(JsonObject& api_data, Core::File& file)
  355. {
  356. StringBuilder builder;
  357. SourceGenerator generator { builder };
  358. generator.appendln("#include <LibGL/GL/glapi.h>");
  359. generator.appendln("#include <LibGL/GLContext.h>");
  360. generator.append("\n");
  361. generator.appendln("extern GL::GLContext* g_gl_context;");
  362. generator.append("\n");
  363. api_data.for_each_member([&](auto& function_name, auto& value) {
  364. VERIFY(value.is_object());
  365. JsonObject const& function = value.as_object();
  366. auto function_definitions = create_function_definitions(function_name, function);
  367. for (auto const& function_definition : function_definitions) {
  368. auto function_generator = generator.fork();
  369. auto return_type = function_definition.return_type;
  370. function_generator.set("name"sv, function_definition.name);
  371. function_generator.set("return_type"sv, return_type);
  372. function_generator.set("implementation"sv, function_definition.implementation);
  373. function_generator.set("variant_gl_type"sv, function_definition.variant_gl_type);
  374. function_generator.append("@return_type@ gl@name@(");
  375. bool first = true;
  376. for (auto const& argument_definition : function_definition.arguments) {
  377. if (!argument_definition.name.has_value() || !argument_definition.cpp_type.has_value())
  378. continue;
  379. auto argument_generator = function_generator.fork();
  380. argument_generator.set("argument_type", argument_definition.cpp_type.value());
  381. argument_generator.set("argument_name", argument_definition.name.value());
  382. if (!first)
  383. argument_generator.append(", ");
  384. first = false;
  385. argument_generator.append("@argument_type@ @argument_name@");
  386. }
  387. function_generator.appendln(")");
  388. function_generator.appendln("{");
  389. if (function_definition.unimplemented) {
  390. function_generator.append(" dbgln(\"gl@name@(");
  391. first = true;
  392. for (auto const& argument_definition : function_definition.arguments) {
  393. if (!argument_definition.name.has_value())
  394. continue;
  395. if (!first)
  396. function_generator.append(", ");
  397. first = false;
  398. if (argument_definition.cpp_type.value().ends_with('*'))
  399. function_generator.append("{:p}");
  400. else if (argument_definition.cpp_type.value() == "GLenum")
  401. function_generator.append("{:#x}");
  402. else
  403. function_generator.append("{}");
  404. }
  405. function_generator.append("): unimplemented\"");
  406. for (auto const& argument_definition : function_definition.arguments) {
  407. if (!argument_definition.name.has_value())
  408. continue;
  409. function_generator.append(", ");
  410. function_generator.append(argument_definition.name.value());
  411. }
  412. function_generator.appendln(");");
  413. function_generator.appendln(" TODO();");
  414. } else {
  415. function_generator.appendln(" if (!g_gl_context)");
  416. if (return_type.ends_with('*'))
  417. function_generator.appendln(" return nullptr;");
  418. else if (return_type == "GLboolean"sv)
  419. function_generator.appendln(" return GL_FALSE;");
  420. else if (return_type == "GLenum"sv)
  421. function_generator.appendln(" return GL_INVALID_OPERATION;");
  422. else if (return_type == "GLuint"sv)
  423. function_generator.appendln(" return 0;");
  424. else if (return_type == "void"sv)
  425. function_generator.appendln(" return;");
  426. else
  427. VERIFY_NOT_REACHED();
  428. function_generator.append(" ");
  429. if (return_type != "void"sv)
  430. function_generator.append("return ");
  431. function_generator.append("g_gl_context->gl_@implementation@(");
  432. first = true;
  433. for (auto const& argument_definition : function_definition.arguments) {
  434. auto argument_generator = function_generator.fork();
  435. auto cast_to = argument_definition.cast_to;
  436. argument_generator.set("argument_name", argument_definition.name.value_or(""));
  437. argument_generator.set("cast_to", cast_to.value_or(""));
  438. if (!first)
  439. argument_generator.append(", ");
  440. first = false;
  441. if (cast_to.has_value())
  442. argument_generator.append("static_cast<@cast_to@>(");
  443. argument_generator.append(argument_definition.expression);
  444. if (cast_to.has_value())
  445. argument_generator.append(")");
  446. }
  447. function_generator.appendln(");");
  448. }
  449. function_generator.appendln("}");
  450. function_generator.append("\n");
  451. }
  452. });
  453. TRY(file.write(generator.as_string_view().bytes()));
  454. return {};
  455. }
  456. ErrorOr<JsonValue> read_entire_file_as_json(StringView filename)
  457. {
  458. auto file = TRY(Core::File::open(filename, Core::File::OpenMode::Read));
  459. auto json_size = TRY(file->size());
  460. auto json_data = TRY(ByteBuffer::create_uninitialized(json_size));
  461. TRY(file->read_entire_buffer(json_data.bytes()));
  462. return JsonValue::from_string(json_data);
  463. }
  464. ErrorOr<int> serenity_main(Main::Arguments arguments)
  465. {
  466. StringView generated_header_path;
  467. StringView generated_implementation_path;
  468. StringView api_json_path;
  469. Core::ArgsParser args_parser;
  470. args_parser.add_option(generated_header_path, "Path to the OpenGL API header file to generate", "generated-header-path", 'h', "generated-header-path");
  471. args_parser.add_option(generated_implementation_path, "Path to the OpenGL API implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path");
  472. args_parser.add_option(api_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path");
  473. args_parser.parse(arguments);
  474. auto json = TRY(read_entire_file_as_json(api_json_path));
  475. VERIFY(json.is_object());
  476. auto api_data = json.as_object();
  477. auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write));
  478. auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write));
  479. TRY(generate_header_file(api_data, *generated_header_file));
  480. TRY(generate_implementation_file(api_data, *generated_implementation_file));
  481. return 0;
  482. }