From ade85a0ac2a6be527ae504ea801e3dfaea69a676 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sat, 23 Sep 2023 08:28:06 +0200 Subject: OpenGL registry --- .gitignore | 2 + gen_gl.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- include/kit.inl.h | 7 +- source/kit/xml.c | 6 +- source/kit/xml.h | 1 + 5 files changed, 436 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 838f752..fa2160b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /*build*/ /.gl_registry *.swp +kit_gl.h +kit_gl.inl.h gen_inl gen_gl diff --git a/gen_gl.c b/gen_gl.c index aabd13f..1b3f3d2 100644 --- a/gen_gl.c +++ b/gen_gl.c @@ -6,10 +6,25 @@ exit #define KIT_IMPLEMENTATION #include "include/kit.inl.h" -#define MB *1024 * 1024 #define GL_FOLDER ".gl_registry" #define GL_REPO "https://github.com/KhronosGroup/OpenGL-Registry" +typedef struct { + str_t name; + str_t value; +} enum_t; + +typedef struct { + str_t name; + str_builder_t return_type; + DA(str_builder_t) arguments; +} proc_t; + +typedef struct { + str_t name; + DA(str_t) procs; +} feature_t; + int main(int argc, char **argv) { if (path_type(SZ("." PATH_DELIM GL_FOLDER)) == PATH_NONE) { int s = system("git clone --quiet --depth 1 " GL_REPO @@ -36,24 +51,18 @@ int main(int argc, char **argv) { return 1; } - // FIXME - // Optimize memory use - i64 arena_size = 100 MB; - u8 *arena = kit_alloc_dispatch(NULL, KIT_ALLOCATE, arena_size, 0, - NULL); - kit_allocator_t alloc = kit_alloc_buffer(arena_size, arena); - - is_handle_t is = is_wrap_file(f, &alloc); struct timespec t0, t1; + is_handle_t is = is_wrap_file(f, NULL); + timespec_get(&t0, TIME_UTC); - xml_parse_result_t res = xml_parse(is, &alloc); + xml_parse_result_t res = xml_parse(is, NULL); timespec_get(&t1, TIME_UTC); + is_destroy(is); fclose(f); if (res.status != KIT_OK) { printf("XML parse failed.\n"); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, arena); return 1; } @@ -61,8 +70,411 @@ int main(int argc, char **argv) { (t1.tv_nsec - t0.tv_nsec + 500000) / 1000000; printf("XML parsed in %lld milliseconds.\n", diff); + DA(enum_t) enums; + DA(proc_t) procs; + DA(feature_t) features; + +#define DESTROY_ALL_ \ + for (i64 i_ = 0; i_ < procs.size; i_++) { \ + for (i64 j_ = 0; j_ < procs.values[i_].arguments.size; j_++) \ + DA_DESTROY(procs.values[i_].arguments.values[j_]); \ + DA_DESTROY(procs.values[i_].return_type); \ + DA_DESTROY(procs.values[i_].arguments); \ + } \ + for (i64 i_ = 0; i_ < features.size; i_++) \ + DA_DESTROY(features.values[i_].procs); \ + DA_DESTROY(enums); \ + DA_DESTROY(procs); \ + DA_DESTROY(features) + + DA_INIT(enums, 0, NULL); + DA_INIT(procs, 0, NULL); + DA_INIT(features, 0, NULL); + + xml_t *registry = res.xml.children.values + 1; + + for (i64 i = 0; i < registry->children.size; i++) { + xml_t *tag_enums = registry->children.values + i; + if (!AR_EQUAL(tag_enums->tag, SZ("enums"))) + continue; + + for (i64 j = 0; j < tag_enums->children.size; j++) { + xml_t *tag_enum = tag_enums->children.values + j; + if (!AR_EQUAL(tag_enum->tag, SZ("enum"))) + continue; + xml_property_t *pro_name = NULL; + xml_property_t *pro_value = NULL; + for (i64 k = 0; k < tag_enum->properties.size; k++) { + xml_property_t *pro = tag_enum->properties.values + k; + if (AR_EQUAL(pro->name, SZ("name"))) + pro_name = pro; + else if (AR_EQUAL(pro->name, SZ("value"))) + pro_value = pro; + } + if (pro_name == NULL || pro_value == NULL) + continue; + + i8 found = 0; + for (i64 k = 0; k < enums.size; k++) + if (AR_EQUAL(pro_name->value, enums.values[k].name)) { + found = 1; + break; + } + if (found) + continue; + + i64 n = enums.size; + DA_RESIZE(enums, n + 1); + + if (enums.size != n + 1) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + enums.values[n].name = WRAP_STR(pro_name->value); + enums.values[n].value = WRAP_STR(pro_value->value); + } + } + + for (i64 i = 0; i < registry->children.size; i++) { + xml_t *tag_commands = registry->children.values + i; + if (!AR_EQUAL(tag_commands->tag, SZ("commands"))) + continue; + + for (i64 j = 0; j < tag_commands->children.size; j++) { + xml_t *tag_command = tag_commands->children.values + j; + if (!AR_EQUAL(tag_command->tag, SZ("command"))) + continue; + + xml_t *tag_proto = NULL; + xml_t *tag_name = NULL; + + for (i64 k = 0; k < tag_command->children.size; k++) { + tag_proto = tag_command->children.values + k; + if (!AR_EQUAL(tag_proto->tag, SZ("proto"))) + continue; + + for (i64 l = 0; l < tag_proto->children.size; l++) + if (AR_EQUAL(tag_proto->children.values[l].tag, + SZ("name"))) { + tag_name = tag_proto->children.values + l; + break; + } + + break; + } + + if (tag_proto == NULL || tag_name == NULL) + continue; + + i64 n = procs.size; + DA_RESIZE(procs, n + 1); + + if (procs.size != n + 1) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + procs.values[n].name = WRAP_STR(tag_name->text); + procs.values[n].return_type = + xml_full_text(tag_proto, NULL).text; + procs.values[n].return_type.size -= procs.values[n].name.size; + + DA_INIT(procs.values[n].arguments, + tag_command->children.size - 1, NULL); + + if (procs.values[n].arguments.size != + tag_command->children.size - 1) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + procs.values[n].arguments.size = 0; + + for (i64 k = 0; k < tag_command->children.size; k++) { + xml_t *tag_param = tag_command->children.values + k; + if (AR_EQUAL(tag_param->tag, SZ("param"))) + procs.values[n] + .arguments.values[procs.values[n].arguments.size++] = + xml_full_text(tag_param, NULL).text; + } + } + } + + for (i64 i = 0; i < registry->children.size; i++) { + xml_t *tag_feature = registry->children.values + i; + if (!AR_EQUAL(tag_feature->tag, SZ("feature"))) + continue; + + xml_property_t *pro_name = NULL; + for (i64 k = 0; k < tag_feature->properties.size; k++) { + xml_property_t *pro = tag_feature->properties.values + k; + if (AR_EQUAL(pro->name, SZ("name"))) + pro_name = pro; + } + if (pro_name == NULL) + continue; + + i64 n = features.size; + DA_RESIZE(features, n + 1); + + if (features.size != n + 1) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + features.values[n].name = WRAP_STR(pro_name->value); + DA_INIT(features.values[n].procs, 0, NULL); + + for (i64 j = 0; j < tag_feature->children.size; j++) { + xml_t *tag_require = tag_feature->children.values + j; + if (!AR_EQUAL(tag_require->tag, SZ("require"))) + continue; + + i64 m = features.values[n].procs.size; + DA_RESIZE(features.values[n].procs, + m + tag_require->children.size); + + if (features.values[n].procs.size != + m + tag_require->children.size) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + features.values[n].procs.size = m; + + for (i64 k = 0; k < tag_require->children.size; k++) { + xml_t *tag_command = tag_require->children.values + k; + if (!AR_EQUAL(tag_command->tag, SZ("command"))) + continue; + + pro_name = NULL; + for (i64 k = 0; k < tag_command->properties.size; k++) { + xml_property_t *pro = tag_command->properties.values + k; + if (AR_EQUAL(pro->name, SZ("name"))) + pro_name = pro; + } + if (pro_name == NULL) + continue; + + features.values[n] + .procs.values[features.values[n].procs.size++] = WRAP_STR( + pro_name->value); + } + } + + if (features.values[n].procs.size == 0) { + DA_DESTROY(features.values[n].procs); + --features.size; + } + } + + for (i64 r = 0; r < registry->children.size; r++) { + xml_t *tag_extensions = registry->children.values + r; + if (!AR_EQUAL(tag_extensions->tag, SZ("extensions"))) + continue; + + for (i64 i = 0; i < tag_extensions->children.size; i++) { + xml_t *tag_extension = tag_extensions->children.values + i; + if (!AR_EQUAL(tag_extension->tag, SZ("extension"))) + continue; + + xml_property_t *pro_name = NULL; + for (i64 k = 0; k < tag_extension->properties.size; k++) { + xml_property_t *pro = tag_extension->properties.values + k; + if (AR_EQUAL(pro->name, SZ("name"))) + pro_name = pro; + } + if (pro_name == NULL) + continue; + + i64 n = features.size; + DA_RESIZE(features, n + 1); + + if (features.size != n + 1) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + features.values[n].name = WRAP_STR(pro_name->value); + DA_INIT(features.values[n].procs, 0, NULL); + + for (i64 j = 0; j < tag_extension->children.size; j++) { + xml_t *tag_require = tag_extension->children.values + j; + if (!AR_EQUAL(tag_require->tag, SZ("require"))) + continue; + + i64 m = features.values[n].procs.size; + DA_RESIZE(features.values[n].procs, + m + tag_require->children.size); + + if (features.values[n].procs.size != + m + tag_require->children.size) { + printf("Bad alloc.\n"); + DESTROY_ALL_; + return 1; + } + + features.values[n].procs.size = m; + + for (i64 k = 0; k < tag_require->children.size; k++) { + xml_t *tag_command = tag_require->children.values + k; + if (!AR_EQUAL(tag_command->tag, SZ("command"))) + continue; + + pro_name = NULL; + for (i64 k = 0; k < tag_command->properties.size; k++) { + xml_property_t *pro = tag_command->properties.values + k; + if (AR_EQUAL(pro->name, SZ("name"))) + pro_name = pro; + } + if (pro_name == NULL) + continue; + + features.values[n] + .procs.values[features.values[n].procs.size++] = + WRAP_STR(pro_name->value); + } + } + + if (features.values[n].procs.size == 0) { + DA_DESTROY(features.values[n].procs); + --features.size; + } + } + } + + f = fopen("kit_gl.h", "wb"); + + if (f == NULL) { + printf("Failed to write kit_gl.inl.h.\n"); + DESTROY_ALL_; + return 1; + } + + fprintf(f, "#include \n"); + fprintf(f, "#include \n"); + fprintf(f, "#ifdef _WIN32\n"); + fprintf(f, "# define GL_API_ENTRY __stdcall\n"); + fprintf(f, "#else\n"); + fprintf(f, "# define GL_API_ENTRY\n"); + fprintf(f, "#endif\n"); + fprintf(f, "typedef unsigned GLenum;\n"); + fprintf(f, "typedef unsigned char GLboolean;\n"); + fprintf(f, "typedef unsigned GLbitfield;\n"); + fprintf(f, "typedef signed char GLbyte;\n"); + fprintf(f, "typedef unsigned char GLubyte;\n"); + fprintf(f, "typedef signed short GLshort;\n"); + fprintf(f, "typedef unsigned short GLushort;\n"); + fprintf(f, "typedef int GLint;\n"); + fprintf(f, "typedef unsigned GLuint;\n"); + fprintf(f, "typedef int GLclampx;\n"); + fprintf(f, "typedef int GLsizei;\n"); + fprintf(f, "typedef float GLfloat;\n"); + fprintf(f, "typedef float GLclampf;\n"); + fprintf(f, "typedef double GLdouble;\n"); + fprintf(f, "typedef double GLclampd;\n"); + fprintf(f, "typedef void * GLeglClientBufferEXT;\n"); + fprintf(f, "typedef void * GLeglImageOES;\n"); + fprintf(f, "typedef char GLchar;\n"); + fprintf(f, "typedef char GLcharARB;\n"); + fprintf(f, "#ifdef __APPLE__\n"); + fprintf(f, " typedef void * GLhandleARB;\n"); + fprintf(f, "#else\n"); + fprintf(f, " typedef unsigned GLhandleARB;\n"); + fprintf(f, "#endif\n"); + fprintf(f, "typedef unsigned short GLhalf;\n"); + fprintf(f, "typedef unsigned short GLhalfARB;\n"); + fprintf(f, "typedef int GLfixed;\n"); + fprintf(f, "typedef intptr_t GLintptr;\n"); + fprintf(f, "typedef intptr_t GLintptrARB;\n"); + fprintf(f, "typedef intptr_t GLsizeiptr;\n"); + fprintf(f, "typedef intptr_t GLsizeiptrARB;\n"); + fprintf(f, "typedef long long GLint64;\n"); + fprintf(f, "typedef long long GLint64EXT;\n"); + fprintf(f, "typedef unsigned long long GLuint64;\n"); + fprintf(f, "typedef unsigned long long GLuint64EXT;\n"); + fprintf(f, "typedef unsigned short GLhalfNV;\n"); + fprintf(f, "typedef intptr_t GLvdpauSurfaceNV;\n"); + fprintf(f, "typedef struct __GLsync * GLsync;\n"); + fprintf(f, "struct _cl_context;\n"); + fprintf(f, "struct _cl_event;\n"); + fprintf(f, + "typedef void (GL_API_ENTRY *GLDEBUGPROC)(GLenum " + "source,GLenum type,GLuint id,GLenum severity,GLsizei " + "length,const GLchar *message,const void *userParam);\n"); + fprintf(f, + "typedef void (GL_API_ENTRY *GLDEBUGPROCARB)(GLenum " + "source,GLenum type,GLuint id,GLenum severity,GLsizei " + "length,const GLchar *message,const void *userParam);\n"); + fprintf(f, + "typedef void (GL_API_ENTRY *GLDEBUGPROCKHR)(GLenum " + "source,GLenum type,GLuint id,GLenum severity,GLsizei " + "length,const GLchar *message,const void *userParam);\n"); + fprintf(f, "typedef void (GL_API_ENTRY *GLDEBUGPROCAMD)(GLuint " + "id,GLenum category,GLenum severity,GLsizei " + "length,const GLchar *message,void *userParam);\n"); + fprintf(f, "typedef void (GL_API_ENTRY *GLVULKANPROCNV)(void);\n"); + + for (i64 i = 0; i < enums.size; i++) + fprintf(f, "#define %-80s %s\n", BS(enums.values[i].name), + BS(enums.values[i].value)); + + for (i64 i = 0; i < procs.size; i++) { + fprintf(f, "typedef %-20s(* proc_%-56s)(", + BS(procs.values[i].return_type), + BS(procs.values[i].name)); + for (i64 j = 0; j < procs.values[i].arguments.size; j++) { + if (j > 0) + fprintf(f, ", "); + fprintf(f, "%s", BS(procs.values[i].arguments.values[j])); + } + fprintf(f, ");\n"); + } + + for (i64 i = 0; i < procs.size; i++) + fprintf(f, "extern proc_%-56s %s;\n", BS(procs.values[i].name), + BS(procs.values[i].name)); + + fprintf(f, "int gl_load_procs(void);\n"); + + fclose(f); + + f = fopen("kit_gl.inl.h", "wb"); + + fprintf(f, "#include \"kit_gl.h\"\n"); + + for (i64 i = 0; i < procs.size; i++) + fprintf(f, "proc_%-56s %-56s= NULL;\n", BS(procs.values[i].name), + BS(procs.values[i].name)); + + fprintf(f, "#ifndef GL_LOAD_PROC\n"); + fprintf(f, "# define GL_LOAD_PROC(name_)\n"); + fprintf(f, "#endif\n"); + + fprintf(f, "int gl_load_procs(void) {\n"); + + for (i64 i = 0; i < features.size; i++) { + fprintf(f, "#ifdef %s\n", BS(features.values[i].name)); + for (i64 j = 0; j < features.values[i].procs.size; j++) + fprintf(f, " GL_LOAD_PROC(%s);\n", + BS(features.values[i].procs.values[j])); + fprintf(f, "#endif\n"); + } + + fprintf(f, " return 1;\n"); + fprintf(f, "}\n"); + + fclose(f); + + DESTROY_ALL_; xml_destroy(&res.xml); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, arena); return 0; } diff --git a/include/kit.inl.h b/include/kit.inl.h index 7b7407d..aa3740d 100644 --- a/include/kit.inl.h +++ b/include/kit.inl.h @@ -1942,6 +1942,7 @@ void kit_xml_destroy(kit_xml_t *xml); # define xml_full_text kit_xml_full_text # define xml_destroy kit_xml_destroy # define xml_t kit_xml_t +# define xml_property_t kit_xml_property_t # define xml_parse_result_t kit_xml_parse_result_t # define xml_text_t kit_xml_text_t #endif @@ -4576,7 +4577,8 @@ static kit_status_t kit_xml_append_text_(str_builder_t *buf, assert(buf->size == n + xml->text.size); if (buf->size != n + xml->text.size) return KIT_ERROR_BAD_ALLOC; - memcpy(buf->values + n, xml->text.values, xml->text.size); + if (xml->text.size > 0) + memcpy(buf->values + n, xml->text.values, xml->text.size); for (i64 i = 0; i < xml->children.size; i++) { kit_status_t s = kit_xml_append_text_(buf, xml->children.values + i); @@ -4590,7 +4592,8 @@ static kit_status_t kit_xml_append_text_(str_builder_t *buf, assert(buf->size == n + tail.size); if (buf->size != n + tail.size) return KIT_ERROR_BAD_ALLOC; - memcpy(buf->values + n, tail.values, tail.size); + if (tail.size > 0) + memcpy(buf->values + n, tail.values, tail.size); } return KIT_OK; } diff --git a/source/kit/xml.c b/source/kit/xml.c index a9d18e3..c62ee82 100644 --- a/source/kit/xml.c +++ b/source/kit/xml.c @@ -373,7 +373,8 @@ static kit_status_t kit_xml_append_text_(str_builder_t *buf, if (buf->size != n + xml->text.size) return KIT_ERROR_BAD_ALLOC; - memcpy(buf->values + n, xml->text.values, xml->text.size); + if (xml->text.size > 0) + memcpy(buf->values + n, xml->text.values, xml->text.size); for (i64 i = 0; i < xml->children.size; i++) { kit_status_t s = kit_xml_append_text_(buf, @@ -393,7 +394,8 @@ static kit_status_t kit_xml_append_text_(str_builder_t *buf, if (buf->size != n + tail.size) return KIT_ERROR_BAD_ALLOC; - memcpy(buf->values + n, tail.values, tail.size); + if (tail.size > 0) + memcpy(buf->values + n, tail.values, tail.size); } return KIT_OK; diff --git a/source/kit/xml.h b/source/kit/xml.h index 6e04878..0bd5744 100644 --- a/source/kit/xml.h +++ b/source/kit/xml.h @@ -55,6 +55,7 @@ void kit_xml_destroy(kit_xml_t *xml); # define xml_full_text kit_xml_full_text # define xml_destroy kit_xml_destroy # define xml_t kit_xml_t +# define xml_property_t kit_xml_property_t # define xml_parse_result_t kit_xml_parse_result_t # define xml_text_t kit_xml_text_t #endif -- cgit v1.2.3