1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
27 // Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
29 #include "vogl_core.h"
30 #include "vogl_console.h"
31 #include "vogl_colorized_console.h"
32 #include "vogl_find_files.h"
33 #include "vogl_file_utils.h"
34 #include "vogl_command_line_params.h"
35 #include "vogl_cfile_stream.h"
36 #include "vogl_vector2d.h"
37 #include "vogl_json.h"
38 #include "vogl_vec_interval.h"
39 #include "vogl_radix_sort.h"
40 #include "vogl_regex.h"
41 #include "vogl_hash_map.h"
44 #include "tinyxml/tinyxml.h"
46 #define VOGL_NAMESPACES_HEADER
47 #define VOGL_NAMESPACES_IMPLEMENTATION
48 #include "../voglcommon/vogl_namespaces.h"
52 //-------------------------------------------------------------------------------------------------------------------------------
53 // Command line options
54 //-------------------------------------------------------------------------------------------------------------------------------
55 static command_line_param_desc g_command_line_param_descs[] =
57 { "debug", 0, false, NULL },
58 { "verbose", 0, false, NULL },
59 { "find", 0, false, NULL },
60 { "func_regex", 1, false, NULL },
61 { "param_regex", 1, false, NULL },
62 { "category_regex", 1, false, NULL },
63 { "ctype_regex", 1, false, NULL },
64 { "namespace_regex", 1, false, NULL },
65 { "srcdir", 1, false, NULL },
68 //-----------------------------------------------------------------------------------------------------------------------
70 //-------------------------------------------------------------------------------------------------------------------------------
79 static const char *g_lib_api_prefixes[] =
87 //-------------------------------------------------------------------------------------------------------------------------------
89 //-------------------------------------------------------------------------------------------------------------------------------
90 static const char *g_gl_vendor_suffixes[] =
92 "NV", "INTEL", "SGIS", "SGIX", "SUN", "NVX", "OES", "AMD", "ATI", "OES", "3DFX", "PGI", "INGR", "IBM"
95 //-------------------------------------------------------------------------------------------------------------------------------
96 // GL/GLX/WGL/etc. function specs
97 //-------------------------------------------------------------------------------------------------------------------------------
98 struct gl_function_param
100 dynamic_string m_name;
101 dynamic_string m_type;
102 dynamic_string m_ctype;
103 dynamic_string m_ctype_enum;
104 dynamic_string m_direction;
105 dynamic_string m_semantic; // array, reference, value
106 dynamic_string m_array_size;
119 m_ctype_enum.clear();
122 m_array_size.clear();
126 void print(FILE *pFile) const
128 vogl_fprintf(pFile, "Name: \"%s\", Type: \"%s\", Direction: \"%s\", Semantic: \"%s\", ArraySize: \"%s\", Retained: %u\n", m_name.get_ptr(), m_type.get_ptr(), m_direction.get_ptr(), m_semantic.get_ptr(), m_array_size.get_ptr(), m_retained);
132 //-----------------------------------------------------------------------------------------------------------------------
133 // struct gl_function_def
134 //-----------------------------------------------------------------------------------------------------------------------
135 struct gl_function_def
137 dynamic_string m_name; // func name from spec file, without the gl/glx/wgl/etc. prefix
138 dynamic_string m_full_name; // full func name, with prefix
139 vogl::vector<dynamic_string> m_param_names;
141 dynamic_string m_return;
142 dynamic_string m_return_ctype;
143 dynamic_string m_return_ctype_enum;
145 vogl::vector<gl_function_param> m_params;
146 dynamic_string m_category;
147 dynamic_string m_version;
148 dynamic_string m_profile;
149 dynamic_string m_deprecated;
161 m_param_names.clear();
163 m_return_ctype.clear();
164 m_return_ctype_enum.clear();
169 m_deprecated.clear();
171 m_notlistable = false;
174 void print(FILE *pFile) const
176 vogl_fprintf(pFile, "Name: \"%s\", ParamNames: %u, Params: %u, Return: \"%s\", Category: \"%s\", Version: \"%s\", Profile: \"%s\", Deprecated: \"%s\", Lib: \"%s\" notlistable: %u\n",
178 m_param_names.size(),
181 m_category.get_ptr(),
184 m_deprecated.get_ptr(),
185 g_lib_api_prefixes[m_lib],
190 for (uint i = 0; i < m_params.size(); i++)
192 vogl_fprintf(pFile, " ");
193 m_params[i].print(pFile);
195 vogl_fprintf(pFile, "\n");
199 dynamic_string get_param_proto() const
201 dynamic_string proto;
202 for (uint param_index = 0; param_index < m_params.size(); param_index++)
204 const gl_function_param ¶m = m_params[param_index];
206 proto.format_append("%s%s%s", param.m_ctype.get_ptr(), param.m_ctype.ends_with("*") ? "" : " ", param.m_name.get_ptr());
207 if (param_index != m_params.size() - 1)
208 proto.format_append(", ");
213 dynamic_string get_param_args() const
215 dynamic_string proto;
216 for (uint param_index = 0; param_index < m_params.size(); param_index++)
218 proto.format_append("%s", m_params[param_index].m_name.get_ptr());
219 if (param_index != m_params.size() - 1)
220 proto.format_append(", ");
225 const char *get_lib_name() const
227 return g_lib_api_prefixes[m_lib];
231 typedef vogl::vector<gl_function_def> gl_function_def_vec;
233 //-----------------------------------------------------------------------------------------------------------------------
234 // struct gl_string_key_comparer
235 //-----------------------------------------------------------------------------------------------------------------------
236 struct gl_string_key_comparer
238 bool operator()(const dynamic_string &lhs, const dynamic_string &rhs) const
240 return lhs.compare(rhs, true) < 0;
244 typedef std::map<dynamic_string, dynamic_string, gl_string_key_comparer> gl_string_map;
245 typedef std::set<dynamic_string, gl_string_key_comparer> gl_string_set;
247 //-----------------------------------------------------------------------------------------------------------------------
248 // class gl_function_specs
249 //-----------------------------------------------------------------------------------------------------------------------
250 class gl_function_specs
262 gl_function_specs &operator+=(const gl_function_specs &other)
264 m_funcs.append(other.m_funcs);
270 return m_funcs.size();
273 const gl_function_def &operator[](uint i) const
278 gl_function_def &operator[](uint i)
283 const gl_function_def_vec &get_funcs_vec() const
288 gl_function_def_vec &get_funcs_vec()
293 int find_index(const char *pName) const
295 for (uint i = 0; i < m_funcs.size(); i++)
296 if (m_funcs[i].m_name.compare(pName, true) == 0)
302 const gl_function_def *find(const char *pName) const
304 for (uint i = 0; i < m_funcs.size(); i++)
305 if (m_funcs[i].m_name.compare(pName, true) == 0)
311 bool exists(const char *pName) const
313 return find(pName) != NULL;
316 void dump_to_file(const char *pFilename) const
318 FILE *pFile = vogl_fopen(pFilename, "w");
321 console::info("--- Dumping %u GL function specs to file \"%s\"\n", m_funcs.size(), pFilename);
323 vogl_fprintf(pFile, "Functions:\n");
324 for (uint i = 0; i < m_funcs.size(); i++)
326 m_funcs[i].print(pFile);
329 vogl_fprintf(pFile, "Categories:\n");
331 gl_string_set categories;
332 for (uint i = 0; i < m_funcs.size(); i++)
333 categories.insert(m_funcs[i].m_category);
335 for (gl_string_set::const_iterator it = categories.begin(); it != categories.end(); ++it)
336 vogl_fprintf(pFile, "\"%s\"\n", it->get_ptr());
342 bool parse_spec_file(const char *pSpec_filename, gl_lib_t default_gl_lib_type)
344 cfile_stream spec_file(pSpec_filename, cDataStreamReadable);
345 if (!spec_file.is_opened())
347 console::error("Unable to open file \"%s\"!\n", pSpec_filename);
351 dynamic_string cur_function_def;
352 vogl::vector<dynamic_string> cur_function_param_names;
353 gl_function_def *pCur_func_def = NULL;
355 uint max_num_params = 0;
356 uint total_functions = 0;
358 dynamic_string line_str;
359 while (spec_file.get_remaining())
361 if (!spec_file.read_line(line_str))
366 int comment_ofs = line_str.find_left('#');
367 if (comment_ofs >= 0)
369 line_str.truncate(comment_ofs);
373 if (line_str.is_empty())
376 if (line_str.find_left(':') >= 0)
378 cur_function_def.clear();
379 pCur_func_def = NULL;
380 cur_function_param_names.clear();
385 //printf("%s\n", line_str.get_ptr());
387 int paren_start = line_str.find_left('(');
388 int paren_end = line_str.find_right(')');
389 bool is_func_def = !vogl_isspace(line_str[0]) && ((paren_start >= 0) && (paren_end >= 0) && (paren_end > paren_start));
393 cur_function_def.set(line_str).left(paren_start).trim();
394 if (cur_function_def.is_empty())
396 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
399 cur_function_def = cur_function_def;
401 dynamic_string param_names(line_str);
402 param_names.mid(paren_start + 1, paren_end - paren_start - 1).trim();
404 cur_function_param_names.resize(0);
407 while (cur_ofs < (int)param_names.get_len())
409 int next_comma_ofs = param_names.find_left(',', cur_ofs);
411 dynamic_string cur_param_name(param_names);
412 if (next_comma_ofs < 0)
414 cur_param_name.right(cur_ofs).trim();
415 cur_ofs = param_names.get_len();
419 cur_param_name.mid(cur_ofs, next_comma_ofs - cur_ofs).trim();
420 cur_ofs = next_comma_ofs + 1;
423 if (!cur_param_name.is_empty())
425 cur_function_param_names.push_back(cur_param_name);
429 console::error("Empty parameter name: %s\n", line_str.get_ptr());
434 printf("Function: \"%s\", Params %u:\n", cur_function_def.get_ptr(), cur_function_param_names.size());
435 for (uint i = 0; i < cur_function_param_names.size(); i++)
437 printf(" %s\n", cur_function_param_names[i].get_ptr());
442 max_num_params = math::maximum(max_num_params, cur_function_param_names.size());
445 pCur_func_def = m_funcs.enlarge(1);
446 pCur_func_def->m_name = cur_function_def;
447 pCur_func_def->m_param_names = cur_function_param_names;
448 pCur_func_def->m_lib = default_gl_lib_type;
450 else if ((!cur_function_def.is_empty()) && pCur_func_def && vogl_isspace(line_str[0]))
452 vogl::vector<dynamic_string> func_attribute_tokens;
453 line_str.tokenize(" \t", func_attribute_tokens);
455 if (func_attribute_tokens.is_empty())
457 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
461 if (func_attribute_tokens[0] == "return")
463 if (func_attribute_tokens.size() != 2)
465 console::error("Expected return type on line: %s\n", line_str.get_ptr());
468 pCur_func_def->m_return = func_attribute_tokens[1];
470 else if (func_attribute_tokens[0] == "param")
472 if ((func_attribute_tokens.size() < 5) || (func_attribute_tokens.size() > 7))
474 console::error("Unexpected number of param tokens on line: %s\n", line_str.get_ptr());
478 if ((func_attribute_tokens[3] != "in") && (func_attribute_tokens[3] != "out"))
480 console::error("Unexpected param direction on line: %s\n", line_str.get_ptr());
484 if (func_attribute_tokens[4].find_left("array[") == 0)
486 // special case for glx.spec
487 int open_bracket = func_attribute_tokens[4].find_left('[');
488 int close_bracket = func_attribute_tokens[4].find_left(']');
489 if (open_bracket < close_bracket)
491 func_attribute_tokens.push_back(dynamic_string(func_attribute_tokens[4]));
492 func_attribute_tokens.back().right(open_bracket);
493 func_attribute_tokens[4].truncate(open_bracket);
497 if ((func_attribute_tokens[4] != "value") && (func_attribute_tokens[4] != "array") && (func_attribute_tokens[4] != "reference"))
499 console::error("Unexpected param semantic on line: %s\n", line_str.get_ptr());
503 gl_function_param *pParam = pCur_func_def->m_params.enlarge(1);
505 if (func_attribute_tokens.back() == "retained")
507 pParam->m_retained = true;
508 func_attribute_tokens.resize(func_attribute_tokens.size() - 1);
511 //param pname GetTextureParameter in value
512 //param params Float32 out array [COMPSIZE(pname)]
513 pParam->m_name = func_attribute_tokens[1];
514 pParam->m_type = func_attribute_tokens[2];
515 pParam->m_direction = func_attribute_tokens[3];
516 pParam->m_semantic = func_attribute_tokens[4];
517 if (pParam->m_semantic == "array")
519 if ((func_attribute_tokens[5][0] != '[') || (func_attribute_tokens[5].back() != ']'))
521 console::error("Unexpected array size on line: %s\n", line_str.get_ptr());
525 pParam->m_array_size = func_attribute_tokens[5];
528 int slash_ofs = pParam->m_array_size.find_left('/');
531 pParam->m_array_size.set_char(slash_ofs, ',');
534 else if (func_attribute_tokens.size() != 5)
536 console::error("Unexpected number of tokens on line: %s\n", line_str.get_ptr());
540 else if (func_attribute_tokens[0] == "category")
542 pCur_func_def->m_category = func_attribute_tokens[1];
544 if (pCur_func_def->m_category == "gl")
545 pCur_func_def->m_lib = cGL;
546 else if (pCur_func_def->m_category == "glX")
547 pCur_func_def->m_lib = cGLX;
548 else if (pCur_func_def->m_category == "wgl")
549 pCur_func_def->m_lib = cWGL;
550 else if (pCur_func_def->m_category == "glu")
551 pCur_func_def->m_lib = cGLU;
554 // lib is default_gl_lib_type
557 else if (func_attribute_tokens[0] == "version")
559 if (func_attribute_tokens.size() != 2)
561 console::error("Invalid version param on line: %s\n", line_str.get_ptr());
565 pCur_func_def->m_version = func_attribute_tokens[1];
567 else if (func_attribute_tokens[0] == "profile")
569 if (func_attribute_tokens.size() != 2)
571 console::error("Invalid profile param on line: %s\n", line_str.get_ptr());
575 pCur_func_def->m_profile = func_attribute_tokens[1];
577 else if (func_attribute_tokens[0] == "deprecated")
579 if (func_attribute_tokens.size() != 2)
581 console::error("Invalid deprecated param on line: %s\n", line_str.get_ptr());
585 pCur_func_def->m_deprecated = func_attribute_tokens[1];
587 else if (func_attribute_tokens[0] == "dlflags")
589 if (func_attribute_tokens.size() != 2)
591 console::error("Invalid dlflags on line: %s\n", line_str.get_ptr());
595 if ((func_attribute_tokens[1] != "notlistable") && (func_attribute_tokens[1] != "handcode") && (func_attribute_tokens[1] != "prepad"))
597 console::error("Unrecognized dlflags on line: %s\n", line_str.get_ptr());
601 pCur_func_def->m_notlistable = (func_attribute_tokens[1] == "notlistable");
607 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
611 for (uint i = 0; i < m_funcs.size(); i++)
613 m_funcs[i].m_full_name.format("%s%s", g_lib_api_prefixes[m_funcs[i].m_lib], m_funcs[i].m_name.get_ptr());
619 bool parse_gl_xml_file(const char *pFilename)
621 TiXmlDocument gl_xml;
622 if (!gl_xml.LoadFile(pFilename))
624 console::error("Failed loading %s!\n", pFilename);
628 const TiXmlElement *pRoot = gl_xml.RootElement();
629 const char *pName = pRoot->Attribute("name");
630 if ((!pName) || (strcmp(pName, "gl")))
632 console::error("Invalid root element in %s!\n", pFilename);
636 const TiXmlElement *pLibraries = pRoot->FirstChildElement("libraries");
637 const TiXmlElement *pExtensions = pRoot->FirstChildElement("extensions");
638 if ((!pLibraries) || (!pExtensions))
640 console::error("Couldn't find libraries and/or extensions elements in %s!\n", pFilename);
644 const TiXmlElement *pLibrary = pLibraries->FirstChildElement();
647 const char *pName = pLibrary->Attribute("name");
650 if (!parse_gl_xml_function_defs(pFilename, pName, pLibrary->FirstChildElement()))
654 pLibrary = pLibrary->NextSiblingElement();
657 const TiXmlElement *pCur_extension = pExtensions->FirstChildElement();
658 while (pCur_extension)
660 const char *pExt_name = pCur_extension->Attribute("name");
663 console::error("Couldn't find extension name attribute in %s!\n", pFilename);
667 if (!parse_gl_xml_function_defs(pFilename, pExt_name, pCur_extension->FirstChildElement()))
670 pCur_extension = pCur_extension->NextSiblingElement();
677 gl_function_def_vec m_funcs;
679 bool parse_gl_xml_function_defs(const char *pFilename, const char *pCategory, const TiXmlElement *pFunctions)
683 if ((pFunctions->Value()) && (strcmp(pFunctions->Value(), "functions") == 0))
685 const TiXmlElement *pFunction = pFunctions->FirstChildElement();
688 if ((pFunction->Value()) && (strcmp(pFunction->Value(), "function") == 0))
690 const char *pType = pFunction->Attribute("type");
691 const char *pName = pFunction->Attribute("name");
692 if ((!pType) || (!pName))
694 console::error("Expected function name and type in file %s\n", pFilename);
698 gl_function_def gl_func;
701 gl_func.m_full_name = pName;
702 gl_func.m_name = pName;
704 if (gl_func.m_name.begins_with("glX", true))
706 gl_func.m_name.right(3);
707 gl_func.m_lib = cGLX;
709 else if (gl_func.m_name.begins_with("glu", true))
711 gl_func.m_name.right(3);
712 gl_func.m_lib = cGLU;
714 else if (gl_func.m_name.begins_with("wgl", true))
716 gl_func.m_name.right(3);
717 gl_func.m_lib = cWGL;
719 else if (gl_func.m_name.begins_with("gl", true))
721 gl_func.m_name.right(2);
726 //console::warning("Unknown function prefix from XML, assuming \"gl\": %s\n", gl_func.m_name.get_ptr());
728 gl_func.m_full_name.format("%s%s", "gl", pName);
731 gl_func.m_category = pCategory;
732 gl_func.m_return = pType;
734 const TiXmlElement *pParams = pFunction->FirstChildElement();
737 if (strcmp(pParams->Value(), "param") == 0)
739 const char *pParam_type = pParams->Attribute("type");
740 const char *pParam_name = pParams->Attribute("name");
741 if ((!pParam_type) || (!pParam_name))
743 console::error("Expected parameter type and name in file %s\n", pFilename);
747 gl_function_param param;
749 param.m_name = pParam_name;
750 param.m_type = pParam_type;
751 gl_func.m_params.push_back(param);
753 pParams = pParams->NextSiblingElement();
756 if ((gl_func.m_params.size() == 1) && (gl_func.m_params[0].m_type == "") && (gl_func.m_params[0].m_name == "void"))
757 gl_func.m_params.resize(0);
759 m_funcs.push_back(gl_func);
762 pFunction = pFunction->NextSiblingElement();
766 pFunctions = pFunctions->NextSiblingElement();
773 //-----------------------------------------------------------------------------------------------------------------------
774 // apitrace glapi.py parsing
775 //-----------------------------------------------------------------------------------------------------------------------
778 const char *m_pSpec_return_type;
779 const char *m_pApitrace_return_type;
780 vogl_namespace_t m_namespace;
781 } g_apitrace_return_type_aliases[] =
783 { "void", "Void", VOGL_NAMESPACE_INVALID },
784 { "GLenum", "GLenum_error", VOGL_NAMESPACE_INVALID },
785 { "const GLubyte *", "String(Const(GLubyte))", VOGL_NAMESPACE_INVALID },
786 { "GLuint", "Handle(\"list\", GLuint, \"range\")", VOGL_NAMESPACE_LISTS },
787 { "GLint", "Alias(\"GLint\", GLenum)", VOGL_NAMESPACE_INVALID },
788 { "GLvoid*", "GLmap", VOGL_NAMESPACE_INVALID },
789 { "GLuint", "GLprogram", VOGL_NAMESPACE_PROGRAMS },
790 { "GLuint", "GLshader", VOGL_NAMESPACE_SHADERS },
791 { "GLint", "GLlocation", VOGL_NAMESPACE_LOCATIONS },
792 { "GLubyte *", "String(Const(GLubyte))", VOGL_NAMESPACE_INVALID },
793 { "GLint", "GLlocationARB", VOGL_NAMESPACE_LOCATIONS },
794 { "GLuint", "Handle(\"fragmentShaderATI\", GLuint, \"range\")", VOGL_NAMESPACE_FRAGMENT_SHADER_ATI }
797 const uint APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE = sizeof(g_apitrace_return_type_aliases) / sizeof(g_apitrace_return_type_aliases[0]);
799 //-----------------------------------------------------------------------------------------------------------------------
800 // g_apitrace_param_type_aliases array
801 //-----------------------------------------------------------------------------------------------------------------------
805 const char *m_pSpec_type;
806 const char *m_pApitrace_type;
807 } g_apitrace_param_type_aliases[] =
809 { "GLbitfield", "GLbitfield_access" },
810 { "GLbitfield", "GLbitfield_attrib" },
811 { "GLbitfield", "GLbitfield_barrier" },
812 { "GLbitfield", "GLbitfield_client_attrib" },
813 { "GLbitfield", "GLbitfield_shader" },
814 { "GLbitfield", "GLbitfield_sync_flush" },
815 { "GLuint", "GLpipeline" },
816 { "GLuint", "GLarray" },
817 { "GLuint", "GLarrayAPPLE" },
818 { "GLuint", "GLbuffer" },
819 { "GLuint", "GLfeedback" },
820 { "GLuint", "GLfence" },
821 { "GLuint", "GLframebuffer" },
822 { "GLuint", "GLpipeline" },
823 { "GLuint", "GLprogramARB" },
824 { "GLuint", "GLquery" },
825 { "GLuint", "GLrenderbuffer" },
826 { "GLuint", "GLsampler" },
827 { "GLuint", "GLtexture" },
828 { "GLuint", "GLarray" },
829 { "GLuint", "GLarrayAPPLE" },
830 { "GLuint", "GLbuffer" },
831 { "GLuint", "GLfeedback" },
832 { "GLuint", "GLfence" },
833 { "GLuint", "GLfragmentShaderATI" },
834 { "GLuint", "GLframebuffer" },
835 { "GLuint", "GLlist" },
836 { "GLuint", "GLpipeline" },
837 { "GLuint", "GLprogram" },
838 { "GLuint", "GLprogramARB" },
839 { "GLuint", "GLquery" },
840 { "GLuint", "GLrenderbuffer" },
841 { "GLuint", "GLsampler" },
842 { "GLuint", "GLshader" },
843 { "GLuint", "GLtexture" },
844 { "GLvoid *", "GLpointer" },
845 { "GLvoid", "GLIndexBuffer" },
846 { "GLchar *", "GLstring" },
847 { "const GLvoid *", "GLpointerConst" },
848 { "GLhalf", "GLhalfNV" },
849 { "const GLchar *", "GLstringConst" },
850 { "const GLchar *", "GLstringConstARB" },
851 { "GLchar *", "GLstringARB" },
852 { "GLchar", "GLcharARB" },
853 { "GLint", "GLlocation" },
854 { "GLint", "GLlocationARB" },
855 { "GLenum", "GLenum_int" },
856 { "GLint", "size_bgra" },
857 { "GLenum", "GLenum_mode" },
860 static const uint APITRACE_PARAM_TYPE_ALIASES_ARRAY_SIZE = sizeof(g_apitrace_param_type_aliases) / sizeof(g_apitrace_param_type_aliases[0]);
862 //-----------------------------------------------------------------------------------------------------------------------
863 // struct apitrace_gl_func_param_def
864 //-----------------------------------------------------------------------------------------------------------------------
865 struct apitrace_gl_func_param_def
867 apitrace_gl_func_param_def()
878 m_array_count_str.clear();
879 m_index_count_str.clear();
880 m_string_count_str.clear();
881 m_index_type_str.clear();
884 m_is_pointer = false;
889 m_is_index_buffer = false;
891 m_is_opaque_ctype = false;
894 dynamic_string m_name;
895 dynamic_string m_type;
896 dynamic_string m_gl_type; // actual C type (but without const stuff)
897 vogl_namespace_t m_namespace;
899 dynamic_string m_array_count_str;
900 dynamic_string m_index_count_str;
901 dynamic_string m_string_count_str;
902 dynamic_string m_index_type_str;
910 bool m_is_index_buffer;
912 bool m_is_opaque_ctype;
915 typedef vogl::vector<apitrace_gl_func_param_def> apitrace_gl_func_param_def_array;
917 //-----------------------------------------------------------------------------------------------------------------------
918 // struct apitrace_gl_func_def
919 //-----------------------------------------------------------------------------------------------------------------------
920 struct apitrace_gl_func_def
922 apitrace_gl_func_def()
930 m_return_type.clear();
931 m_return_gl_type.clear();
932 m_has_side_effects = false;
936 dynamic_string m_name;
937 dynamic_string m_return_type;
938 dynamic_string m_return_gl_type; // actual C type (but without const stuff)
939 vogl_namespace_t m_return_namespace;
941 bool m_has_side_effects;
942 apitrace_gl_func_param_def_array m_params;
945 typedef vogl::vector<apitrace_gl_func_def> apitrace_gl_func_def_array;
947 //-----------------------------------------------------------------------------------------------------------------------
948 // class apitrace_func_specs
949 //-----------------------------------------------------------------------------------------------------------------------
951 //#define APITRACE_FUNC_SPECS_DEBUG
953 class apitrace_func_specs
956 apitrace_func_specs()
967 return m_funcs.size();
970 const apitrace_gl_func_def &operator[](uint i) const
975 apitrace_gl_func_def &operator[](uint i)
980 const apitrace_gl_func_def_array &get_funcs_vec() const
985 apitrace_gl_func_def_array &get_funcs_vec()
990 int find_index(const char *pName) const
992 for (uint i = 0; i < m_funcs.size(); i++)
993 if (m_funcs[i].m_name.compare(pName, true) == 0)
999 const apitrace_gl_func_def *find(const char *pName) const
1001 for (uint i = 0; i < m_funcs.size(); i++)
1002 if (m_funcs[i].m_name.compare(pName, true) == 0)
1008 bool exists(const char *pName) const
1010 return find(pName) != NULL;
1013 // Yes this guy is ugly, but it's simple and works on the unmodified Python source glapi.py from apitrace.
1014 // glapi.py was automatically generated, then hand edited. It contains a lot of useful type and array size info, but is still
1015 // incomplete (see glReadPixels() for example, which is missing its array size).
1016 bool parse(const char *pFilename = "apitrace_gl_param_info.txt")
1020 dynamic_string_array param_info_file;
1021 if (!file_utils::read_text_file(pFilename, param_info_file, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
1024 dynamic_string_array unique_types;
1025 dynamic_string_array unique_array_counts;
1027 for (uint line_index = 0; line_index < param_info_file.size(); line_index++)
1029 const dynamic_string &orig_line(param_info_file[line_index]);
1030 dynamic_string line(orig_line);
1032 if (line.begins_with("#"))
1035 int comment_ofs = line.find_right('#');
1036 if (comment_ofs >= 0)
1037 line.left(comment_ofs).trim();
1039 if (!line.begins_with("GlFunction("))
1040 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1042 line.replace("GlFunction(", "", true, NULL, 1);
1044 if (line.ends_with(","))
1047 if (!line.ends_with(")"))
1048 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1050 dynamic_string return_type;
1052 int first_comma = line.find_left(',');
1053 if (first_comma < 0)
1054 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1056 int first_paren = line.find_left('(');
1057 if ((first_paren >= 0) && (first_paren < first_comma))
1059 int matching_paren = find_matching_paren(line, first_paren);
1060 if (matching_paren < 0)
1061 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1063 return_type = dynamic_string(line).left(matching_paren + 1);
1064 line.right(matching_paren + 1).trim();
1065 if (!line.begins_with(","))
1066 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1068 line.right(1).trim();
1072 return_type = dynamic_string(line).left(first_comma);
1073 line.right(first_comma + 1).trim();
1076 if (!line.begins_with("\""))
1077 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1079 int end_quote_ofs = line.find_left('\"', 1);
1080 if (end_quote_ofs < 0)
1081 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1083 dynamic_string func_name(line);
1084 func_name.substring(1, end_quote_ofs);
1086 line.right(end_quote_ofs + 1).trim();
1087 if (!line.begins_with(","))
1088 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1089 line.right(1).trim();
1091 if (!line.begins_with("["))
1092 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1094 int params_end = find_matching_paren(line, 0, '[', ']');
1096 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1098 dynamic_string params(line);
1099 params.substring(1, params_end);
1101 line.right(params_end + 1).trim();
1103 if ((!line.begins_with(",") && !line.begins_with(")")) || !line.ends_with(")"))
1104 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1106 bool func_has_side_effects = true;
1107 if (line.contains("sideeffects=False"))
1108 func_has_side_effects = false;
1110 apitrace_gl_func_def func_def;
1111 func_def.m_name = func_name;
1112 func_def.m_has_side_effects = func_has_side_effects;
1113 func_def.m_return_type = return_type;
1115 func_def.m_return_gl_type = return_type;
1118 for (a = 0; a < APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE; a++)
1120 if (func_def.m_return_gl_type == g_apitrace_return_type_aliases[a].m_pApitrace_return_type)
1122 func_def.m_return_gl_type = g_apitrace_return_type_aliases[a].m_pSpec_return_type;
1123 func_def.m_return_namespace = g_apitrace_return_type_aliases[a].m_namespace;
1127 if (a == APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE)
1129 func_def.m_return_namespace = vogl_find_namespace_from_gl_type(func_def.m_return_gl_type.get_ptr());
1130 if (func_def.m_return_namespace == VOGL_NAMESPACE_INVALID)
1132 // TODO: Here's the list of return/param types that can't be mapped right now - make exception list?
1171 GLbitfield_sync_flush
1173 GLbitfield_client_attrib
1184 //console::warning("%s: Couldn't map namespace %s\n", VOGL_METHOD_NAME, func_def.m_return_gl_type.get_ptr());
1188 #ifdef APITRACE_FUNC_SPECS_DEBUG
1189 printf("--- Func: %s\nReturn Type: %s, HasSideEffects: %u, Namespace: %s\n", func_name.get_ptr(), return_type.get_ptr(), func_has_side_effects, vogl_get_namespace_name(func_def.m_return_namespace));
1194 bool is_out = false;
1195 bool is_pointer = false;
1196 bool is_const = false;
1197 bool is_opaque = false;
1198 bool is_array = false;
1199 bool is_blob = false;
1200 bool is_index_buffer = false;
1201 bool is_string = false;
1202 bool is_opaque_ctype = false;
1203 dynamic_string array_count_str;
1204 dynamic_string index_count_str;
1205 dynamic_string string_count_str;
1206 dynamic_string index_type_str;
1208 if (params.is_empty())
1211 if (params.begins_with("Out("))
1213 else if (!params.begins_with("("))
1214 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1216 int first_paren = params.find_left("(");
1217 if (first_paren < 0)
1218 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1220 int param_end_ofs = find_matching_paren(params, first_paren);
1221 if (param_end_ofs < 0)
1222 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1224 dynamic_string cur_param;
1226 cur_param.substring(first_paren + 1, param_end_ofs);
1228 params.right(param_end_ofs + 1).trim();
1229 if (params.begins_with(","))
1230 params.right(1).trim();
1232 int right_comma = cur_param.find_right(",");
1233 if (right_comma < 0)
1234 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1236 dynamic_string param_name(cur_param);
1237 param_name.right(right_comma + 1).trim();
1238 cur_param.left(right_comma).trim();
1241 while ((paren_ofs = cur_param.find_left('(')) >= 0)
1243 bool get_count_string = false;
1244 bool count_string_is_optional = false;
1245 dynamic_string *pCount_str = &array_count_str;
1247 if (cur_param.begins_with("Out("))
1249 else if (cur_param.begins_with("Pointer("))
1251 else if (cur_param.begins_with("OpaquePointer("))
1256 else if (cur_param.begins_with("Const("))
1258 else if (cur_param.begins_with("OpaqueBlob("))
1262 get_count_string = true;
1264 else if (cur_param.begins_with("Blob("))
1267 get_count_string = true;
1269 else if (cur_param.begins_with("GLIndexBuffer("))
1271 is_index_buffer = true;
1272 get_count_string = true;
1273 pCount_str = &index_count_str;
1275 else if (cur_param.begins_with("OpaqueArray("))
1279 get_count_string = true;
1281 else if (cur_param.begins_with("Array("))
1284 get_count_string = true;
1286 else if (cur_param.begins_with("String("))
1289 get_count_string = true;
1290 count_string_is_optional = true;
1291 pCount_str = &string_count_str;
1293 else if (cur_param.begins_with("Opaque("))
1295 is_opaque_ctype = true;
1298 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1300 int end_paren_ofs = find_matching_paren(cur_param, paren_ofs);
1301 if (end_paren_ofs < 0)
1302 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1304 cur_param.substring(paren_ofs + 1, end_paren_ofs);
1306 if (get_count_string)
1308 if (cur_param.ends_with("\""))
1310 int start_of_count = cur_param.find_right('\"', cur_param.get_len() - 2);
1311 if (start_of_count < 0)
1312 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1314 if (!pCount_str->is_empty())
1315 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1317 *pCount_str = cur_param;
1318 pCount_str->right(start_of_count).trim();
1320 cur_param.left(start_of_count).trim();
1321 if (!cur_param.ends_with(","))
1322 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1324 cur_param.shorten(1).trim();
1328 int comma_ofs = cur_param.find_right(',');
1329 if ((comma_ofs < 0) && (!count_string_is_optional))
1330 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1334 if (!pCount_str->is_empty())
1335 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1336 *pCount_str = cur_param;
1337 pCount_str->right(comma_ofs + 1).trim();
1339 cur_param.left(comma_ofs).trim();
1344 if (is_index_buffer)
1346 index_type_str = *pCount_str;
1347 *pCount_str = cur_param;
1348 cur_param.truncate(0);
1349 if (index_type_str.contains('(') || index_type_str.contains(','))
1350 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1355 if (is_index_buffer)
1356 cur_param = "GLIndexBuffer";
1358 if (cur_param.is_empty())
1359 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1361 if (unique_types.find(cur_param) < 0)
1362 unique_types.push_back(cur_param);
1364 if (unique_array_counts.find(array_count_str) < 0)
1365 unique_array_counts.push_back(array_count_str);
1367 apitrace_gl_func_param_def param_def;
1368 param_def.m_name = param_name;
1369 param_def.m_type = cur_param;
1370 param_def.m_array_count_str = array_count_str;
1371 param_def.m_index_count_str = index_count_str;
1372 param_def.m_string_count_str = string_count_str;
1373 param_def.m_index_type_str = index_type_str;
1374 param_def.m_is_out = is_out;
1375 param_def.m_is_pointer = is_pointer;
1376 param_def.m_is_const = is_const;
1377 param_def.m_is_opaque = is_opaque;
1378 param_def.m_is_array = is_array;
1379 param_def.m_is_blob = is_blob;
1380 param_def.m_is_index_buffer = is_index_buffer;
1381 param_def.m_is_string = is_string;
1382 param_def.m_is_opaque_ctype = is_opaque_ctype;
1384 dynamic_string gl_param_type(param_def.m_type);
1386 if (param_def.m_is_opaque_ctype)
1387 gl_param_type.unquote();
1389 param_def.m_namespace = vogl_find_namespace_from_gl_type(gl_param_type.get_ptr());
1390 if (param_def.m_namespace == VOGL_NAMESPACE_INVALID)
1392 //console::warning("%s: Couldn't map namespace %s\n", VOGL_METHOD_NAME, gl_param_type.get_ptr());
1395 for (uint k = 0; k < APITRACE_PARAM_TYPE_ALIASES_ARRAY_SIZE; k++)
1397 if (gl_param_type == g_apitrace_param_type_aliases[k].m_pApitrace_type)
1399 gl_param_type = g_apitrace_param_type_aliases[k].m_pSpec_type;
1404 if ((param_def.m_is_string) || (param_def.m_is_index_buffer))
1405 gl_param_type.append(" *");
1407 if ((param_def.m_is_array) || (param_def.m_is_blob) || (param_def.m_is_pointer))
1409 gl_param_type.append(" *");
1412 param_def.m_gl_type = gl_param_type;
1414 #ifdef APITRACE_FUNC_SPECS_DEBUG
1415 printf("Name: %s, Type: %s, Out: %u, Pointer: %u, Const: %u, IsOpaque: %u, Array: %u, Blob: %u, IndexBuf: %u, String: %u, OpaqueCType: %u, Namespace: %s\n",
1416 param_name.get_ptr(),
1417 cur_param.get_ptr(),
1418 is_out, is_pointer, is_const, is_opaque, is_array, is_blob, is_index_buffer, is_string, is_opaque_ctype, vogl_get_namespace_name(param_def.m_namespace));
1419 if (array_count_str.get_len())
1420 printf(" ArrayCountStr: %s\n", array_count_str.get_ptr());
1421 if (index_count_str.get_len())
1422 printf(" IndexCountStr: %s\n", index_count_str.get_ptr());
1423 if (string_count_str.get_len())
1424 printf(" StringCountStr: %s\n", string_count_str.get_ptr());
1425 if (index_type_str.get_len())
1426 printf(" IndexTypeStr: %s\n", index_type_str.get_ptr());
1429 func_def.m_params.push_back(param_def);
1432 m_funcs.push_back(func_def);
1434 #ifdef APITRACE_FUNC_SPECS_DEBUG
1439 #ifdef APITRACE_FUNC_SPECS_DEBUG
1440 printf("Unique types:\n");
1441 unique_types.sort();
1442 for (uint i = 0; i < unique_types.size(); i++)
1443 printf("%s\n", unique_types[i].get_ptr());
1447 printf("Unique array counts:\n");
1448 unique_array_counts.sort();
1449 for (uint i = 0; i < unique_array_counts.size(); i++)
1450 printf("%s\n", unique_array_counts[i].get_ptr());
1457 apitrace_gl_func_def_array m_funcs;
1459 bool parse_apitrace_gl_param_info_error(const dynamic_string_array ¶m_info_file, uint line_index)
1461 console::error("Unrecognized line: %s\n", param_info_file[line_index].get_ptr());
1465 static int find_matching_paren(const dynamic_string &str, uint ofs, uint open_char = '(', uint close_char = ')')
1467 bool in_quoted_string = false;
1468 uint param_count = 0;
1470 while (ofs < str.get_len())
1474 if (in_quoted_string)
1478 in_quoted_string = false;
1483 in_quoted_string = true;
1485 else if (c == open_char)
1487 else if (c == close_char)
1501 //-----------------------------------------------------------------------------------------------------------------------
1503 //-----------------------------------------------------------------------------------------------------------------------
1516 const gl_string_map &get_type_map() const
1520 gl_string_map &get_type_map()
1527 return static_cast<uint>(m_tm.size());
1530 bool is_present(const dynamic_string &type_str) const
1532 return m_tm.find(type_str) != m_tm.end();
1536 const dynamic_string *find(const dynamic_string &type_str) const
1538 gl_string_map::const_iterator it(m_tm.find(type_str));
1539 if (it == m_tm.end())
1544 bool parse_file(const char *pFilename)
1546 cfile_stream tm_file(pFilename, cDataStreamReadable);
1547 if (!tm_file.is_opened())
1549 console::error("Unable to open file \"%s\"!\n", pFilename);
1553 dynamic_string line_str;
1554 while (tm_file.get_remaining())
1556 if (!tm_file.read_line(line_str))
1559 line_str.trim_end();
1561 int comment_ofs = line_str.find_left('#');
1562 if (comment_ofs >= 0)
1564 line_str.truncate(comment_ofs);
1565 line_str.trim_end();
1568 if (line_str.is_empty())
1571 // AccumOp,*,*, GLenum,*,*
1573 dynamic_string_array tokens;
1574 line_str.tokenize(",", tokens);
1575 if (tokens.size() != 6)
1577 console::error("Unexpected number of tokens on line: %s\n", line_str.get_ptr());
1581 for (uint i = 0; i < tokens.size(); i++)
1584 if ((tokens[0].is_empty()) || (tokens[1] != "*") || (tokens[2] != "*") ||
1585 (tokens[3].is_empty()) || (tokens[4] != "*") || (tokens[5] != "*"))
1587 console::error("Unexpected token on line: %s\n", line_str.get_ptr());
1591 if (m_tm.find(tokens[0]) != m_tm.end())
1593 console::error("Duplicate spec type on line: %s\n", line_str.get_ptr());
1597 m_tm.insert(std::make_pair(tokens[0], tokens[3]));
1603 //-----------------------------------------------------------------------------------------------------------------------
1605 void dump_to_file(const char *pFilename) const
1607 FILE *pFile = vogl_fopen(pFilename, "w");
1610 console::info("--- Dumping %u GL types to text file \"%s\"\n", static_cast<uint>(m_tm.size()), pFilename);
1612 for (gl_string_map::const_iterator it = m_tm.begin(); it != m_tm.end(); ++it)
1613 vogl_fprintf(pFile, "\"%s\" = \"%s\"\n", it->first.get_ptr(), it->second.get_ptr());
1619 console::error("Failed writing GL types to file \"%s\"!\n", pFilename);
1627 //-----------------------------------------------------------------------------------------------------------------------
1629 //-----------------------------------------------------------------------------------------------------------------------
1632 dynamic_string m_name;
1633 dynamic_string m_def;
1638 typedef vogl::vector<gl_enum_def> gl_enum_def_vec;
1640 typedef std::map<dynamic_string, gl_enum_def_vec, gl_string_key_comparer> gl_enum_def_vec_map;
1649 bool parse_file(const char *pFilename)
1651 cfile_stream enum_file(pFilename, cDataStreamReadable);
1652 if (!enum_file.is_opened())
1654 console::error("Unable to open file \"%s\"!\n", pFilename);
1658 vogl::vector<gl_enum_def_vec_map::iterator> cur_enums;
1659 bool is_define = false;
1660 bool seen_at_least_one_define = false;
1662 dynamic_string line_str;
1663 while (enum_file.get_remaining())
1665 if (!enum_file.read_line(line_str))
1668 line_str.trim_end();
1670 int comment_ofs = line_str.find_left('#');
1671 if (comment_ofs >= 0)
1673 line_str.truncate(comment_ofs);
1674 line_str.trim_end();
1677 if (line_str.is_empty())
1680 int colon_ofs = line_str.find_left(':');
1682 line_str.left(colon_ofs + 1);
1684 dynamic_string_array tokens;
1685 line_str.tokenize(", \t", tokens);
1687 if ((tokens[0] == "passthru:") || (tokens[0] == "profile:") || (tokens[0].find_left("future_use:") >= 0))
1690 if ((colon_ofs >= 0) && (tokens.size()) &&
1691 ((tokens.back() == "enum:") || (tokens.back() == "define:")))
1693 if (seen_at_least_one_define)
1694 cur_enums.resize(0);
1696 is_define = (tokens.back() == "define:");
1698 for (uint i = 0; i < (tokens.size() - 1); i++)
1700 gl_enum_def_vec_map::iterator cur_enum(m_enums.find(tokens[i]));
1701 if (cur_enum == m_enums.end())
1703 cur_enum = m_enums.insert(std::make_pair(tokens[i], gl_enum_def_vec())).first;
1706 cur_enums.push_back(cur_enum);
1709 else if (tokens.size())
1711 if (line_str.find_left('=') >= 0)
1713 seen_at_least_one_define = true;
1715 if ((tokens.size() != 3) || (tokens[1] != "="))
1717 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1721 if ((tokens[0].is_empty()) || (tokens[1].is_empty()))
1723 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1727 if (!cur_enums.size())
1729 console::error("Enum defined outside of enum block: %s\n", line_str.get_ptr());
1734 def.m_name = tokens[0];
1735 def.m_def = tokens[2];
1736 def.m_alias_flag = false;
1737 def.m_define_flag = is_define;
1739 for (uint i = 0; i < cur_enums.size(); i++)
1740 cur_enums[i]->second.push_back(def);
1742 else if (tokens[0] == "use")
1744 seen_at_least_one_define = true;
1746 if (!cur_enums.size())
1748 console::error("Enum defined outside of enum block: %s\n", line_str.get_ptr());
1753 def.m_name = tokens[2];
1754 def.m_def = tokens[1];
1755 def.m_alias_flag = true;
1756 def.m_define_flag = is_define;
1758 for (uint i = 0; i < cur_enums.size(); i++)
1759 cur_enums[i]->second.push_back(def);
1763 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1769 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1774 for (gl_enum_def_vec_map::iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1776 //printf("%s\n", enum_it->first.get_ptr());
1777 gl_enum_def_vec_map::const_iterator alias_it(m_enums.find(enum_it->first));
1778 VOGL_ASSERT(alias_it != m_enums.end());
1781 uint num_unresolved_aliases;
1785 if (++pass_num == 100)
1787 console::error("Typemap alias depth is too deep, or there are circular aliases\n");
1791 num_unresolved_aliases = 0;
1793 for (gl_enum_def_vec_map::iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1795 gl_enum_def_vec &def_vec = enum_it->second;
1796 for (uint i = 0; i < def_vec.size(); i++)
1798 if (!def_vec[i].m_alias_flag)
1801 gl_enum_def_vec_map::const_iterator alias_it(m_enums.find(def_vec[i].m_def));
1802 if (alias_it == m_enums.end())
1804 console::error("Bad alias enum: %s %s\n", def_vec[i].m_def.get_ptr(), def_vec[i].m_name.get_ptr());
1808 const gl_enum_def_vec &alias_def_vec = alias_it->second;
1811 for (j = 0; j < alias_def_vec.size(); j++)
1813 if (alias_def_vec[j].m_name == def_vec[i].m_name)
1817 if (j == alias_def_vec.size())
1819 console::error("Bad alias enum: %s %s\n", def_vec[i].m_def.get_ptr(), def_vec[i].m_name.get_ptr());
1822 if (alias_def_vec[j].m_alias_flag)
1824 num_unresolved_aliases++;
1828 def_vec[i].m_def = alias_def_vec[j].m_def;
1829 def_vec[i].m_alias_flag = false;
1833 } while (num_unresolved_aliases);
1839 void dump_to_text_file(const char *pFilename) const
1841 FILE *pFile = vogl_fopen(pFilename, "w");
1844 console::info("--- Dumping %u GL enums to file %s\n", static_cast<uint>(m_enums.size()), pFilename);
1846 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1848 vogl_fprintf(pFile, "enum \"%s\"\n", enum_it->first.get_ptr());
1849 for (uint i = 0; i < enum_it->second.size(); i++)
1850 vogl_fprintf(pFile, " \"%s\" = \"%s\"\n", enum_it->second[i].m_name.get_ptr(), enum_it->second[i].m_def.get_ptr());
1857 console::error("Failed writing GL enums to file %s\n", pFilename);
1861 bool dump_to_definition_macro_file(const char *pFilename, const char *pPrefix) const
1863 gl_string_map unique_enums;
1864 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1866 for (uint i = 0; i < enum_it->second.size(); i++)
1867 unique_enums.insert(std::make_pair(enum_it->second[i].m_name, enum_it->second[i].m_def));
1870 console::info("--- Generating \"%s\":\n", pFilename);
1872 FILE *pFile = vogl_fopen(pFilename, "w");
1875 console::error("%s: Failed creating file \"%s\"!\n", VOGL_METHOD_NAME, pFilename);
1879 for (gl_string_map::const_iterator it = unique_enums.begin(); it != unique_enums.end(); ++it)
1880 vogl_fprintf(pFile, "#define %s_%s %s\n", pPrefix, it->first.get_ptr(), it->second.get_ptr());
1886 bool dump_to_description_macro_file(const char *pFilename, const char *pPrefix, const gl_types &gl_typemap, const gl_types &alt_gl_typemap) const
1888 console::info("--- Generating \"%s\":\n", pFilename);
1890 FILE *pFile = vogl_fopen(pFilename, "w");
1893 console::error("%s: Failed creating file \"%s\"!\n", VOGL_METHOD_NAME, pFilename);
1897 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1899 vogl_fprintf(pFile, "DEFINE_GL_ENUM_CATEGORY_BEGIN(%s)\n", enum_it->first.get_ptr());
1901 for (uint i = 0; i < enum_it->second.size(); i++)
1903 const dynamic_string *pGLType = NULL;
1904 pGLType = gl_typemap.find(enum_it->first.get_ptr());
1906 pGLType = alt_gl_typemap.find(enum_it->first.get_ptr());
1908 if (enum_it->second[i].m_define_flag)
1910 vogl_fprintf(pFile, "DEFINE_GL_DEFINE_MEMBER(%s, %s, %s_%s)\n",
1912 enum_it->first.get_ptr(),
1913 pPrefix, enum_it->second[i].m_name.get_ptr());
1917 vogl_fprintf(pFile, "DEFINE_GL_ENUM_MEMBER(%s, %s, \"%s\", \"%s_%s\", %s)\n",
1919 enum_it->first.get_ptr(),
1920 pGLType ? pGLType->get_ptr() : "",
1921 pPrefix, enum_it->second[i].m_name.get_ptr(), enum_it->second[i].m_def.get_ptr());
1925 vogl_fprintf(pFile, "DEFINE_GL_ENUM_CATEGORY_END(%s)\n", enum_it->first.get_ptr());
1934 gl_enum_def_vec_map m_enums;
1937 //-----------------------------------------------------------------------------------------------------------------------
1939 //-----------------------------------------------------------------------------------------------------------------------
1940 #define DEF_FUNCTION_PROTO_PARAM_STR "(a,b,c,d,e,f,g,h)"
1944 apitrace_func_specs m_apitrace_gl_func_specs;
1945 gl_function_specs m_gl_xml_functions;
1946 gl_enums m_gl_enumerations;
1947 gl_enums m_glx_enumerations;
1948 gl_enums m_glx_ext_enumerations;
1950 gl_function_specs m_gl_funcs;
1951 gl_function_specs m_glx_funcs;
1952 gl_function_specs m_glxext_funcs;
1954 gl_function_specs m_all_gl_funcs;
1956 dynamic_string_array m_unique_categories;
1958 gl_string_map m_unique_ctype_enums;
1960 gl_types m_gl_typemap;
1961 gl_types m_glx_typemap;
1963 dynamic_string_array m_gl_so_function_exports;
1965 gl_string_set m_all_gl_ctypes;
1966 gl_string_set m_all_gl_categories;
1967 gl_string_set m_all_array_sizes;
1969 gl_string_map m_pointee_types;
1971 dynamic_string_array m_whitelisted_funcs;
1972 dynamic_string_array m_whitelisted_displaylist_funcs;
1973 dynamic_string_array m_nullable_funcs;
1975 dynamic_string_array m_simple_replay_funcs;
1977 dynamic_string_array funcs_with_custom_array_size_macros;
1978 dynamic_string_array custom_return_param_array_size_macros;
1979 dynamic_string_array funcs_with_return_param_array_size_macros;
1981 gl_string_set custom_array_size_macros;
1982 vogl::vector<uint> custom_array_size_macro_indices;
1983 dynamic_string_array custom_array_size_macro_names;
1988 : m_min_vers(0xFFFF), m_max_vers(0)
1992 dynamic_string m_name;
1996 inline bool operator<(const gl_get &rhs) const
1998 if (m_min_vers < rhs.m_min_vers)
2000 else if (m_min_vers == rhs.m_min_vers)
2002 if (m_max_vers < rhs.m_max_vers)
2004 else if (m_max_vers == rhs.m_max_vers)
2005 return m_name < rhs.m_name;
2011 typedef vogl::hash_map<dynamic_string, gl_get> gl_get_hash_map;
2012 gl_get_hash_map m_gl_gets;
2021 // TODO: I'm going to move the "glspec" dir from under bin to raddebugger/glspec (or whatever)
2022 if (!file_utils::does_file_exist("gl.spec"))
2024 if (file_utils::does_file_exist("glspec/gl.spec"))
2026 file_utils::change_directory("glspec");
2027 console::warning("Changing current directory to glspec\n");
2029 else if (file_utils::does_file_exist("../bin/glspec/gl.spec"))
2031 file_utils::change_directory("../bin/glspec");
2032 console::warning("Changing current directory to ../bin/glspec\n");
2036 if (!file_utils::does_file_exist("gl.spec"))
2038 console::error("Can't find find gl.spec, which must be in the current directory!\n");
2042 // -- Load apitrace's GL function defintions, which was auto generated then hand-edited by the apitrace team - we ONLY use this for parameter namespace info and cross referencing (verification)
2043 if (!m_apitrace_gl_func_specs.parse())
2045 console::error("Failed parsing apitrace param info file!\n");
2049 // -- Load gl.xml, auto-generated from various web pages using several Python scripts
2050 if (!m_gl_xml_functions.parse_gl_xml_file("gl.xml"))
2053 // -- Load the various GL/GLX/GLXEXT enum spec files
2054 m_gl_enumerations.parse_file("enum.spec");
2055 m_glx_enumerations.parse_file("glxenum.spec");
2056 m_glx_ext_enumerations.parse_file("glxenumext.spec");
2058 // -- Load the various GL/GLX/GLXEXT func spec files
2059 bool success = m_gl_funcs.parse_spec_file("gl.spec", cGL);
2062 console::error("Failed parsing gl.spec!\n");
2065 success = m_glx_funcs.parse_spec_file("glx.spec", cGLX);
2068 console::error("Failed parsing glx.spec!\n");
2072 success = m_glxext_funcs.parse_spec_file("glxext.spec", cGLX);
2075 console::error("Failed parsing glxext.spec!\n");
2079 // -- Clean up the GLX func definitions
2080 for (uint i = 0; i < m_glxext_funcs.size(); i++)
2082 int glx_index = m_glx_funcs.find_index(m_glxext_funcs[i].m_name.get_ptr());
2085 console::warning("glxext func %s overriding glx definition\n", m_glxext_funcs[i].m_name.get_ptr());
2086 m_glx_funcs.get_funcs_vec().erase_unordered(glx_index);
2089 int gl_index = m_gl_funcs.find_index(m_glxext_funcs[i].m_name.get_ptr());
2092 console::warning("glxext func %s overriding definition\n", m_glxext_funcs[i].m_name.get_ptr());
2093 m_gl_funcs.get_funcs_vec().erase_unordered(gl_index);
2097 for (uint j = 0; j < m_glxext_funcs.size(); j++)
2099 if (m_glxext_funcs[j].m_name.ends_with("SGIX"))
2101 console::message("deleting glxext func %s\n", m_glxext_funcs[j].m_name.get_ptr());
2103 m_glxext_funcs.get_funcs_vec().erase_unordered(j);
2108 // -- Parse the various spec typemap files
2109 success = m_gl_typemap.parse_file("gl.tm");
2112 console::error("Failed parsing gl.tm!\n");
2116 success = m_glx_typemap.parse_file("glx.tm");
2119 console::error("Failed parsing glx.tm!\n");
2123 // -- Determine the ctypes used by all the GL/GLX functions
2124 if (!determine_ctypes("gl", m_gl_funcs, m_gl_typemap, m_glx_typemap))
2126 console::error("Failed determined gl c types!\n");
2130 if (!determine_ctypes("glX", m_glx_funcs, m_glx_typemap, m_gl_typemap))
2132 console::error("Failed determined glX c types!\n");
2136 if (!determine_ctypes("glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap))
2138 console::error("Failed determined glX c types!\n");
2142 // -- Create master list of all GL/GLX/GLXEXT functions
2143 m_all_gl_funcs = m_gl_funcs;
2144 m_all_gl_funcs += m_glx_funcs;
2145 m_all_gl_funcs += m_glxext_funcs;
2147 // -- Determine the unique list of function API categories
2148 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2150 if (m_unique_categories.find(m_all_gl_funcs[i].m_category) < 0)
2151 m_unique_categories.push_back(m_all_gl_funcs[i].m_category);
2154 m_unique_categories.sort();
2156 // -- Load the GL/GLX function export table, generated by dumping the headers of various drivers
2157 if (!load_gl_so_function_export_list("gl_glx_so_export_list.txt", m_gl_so_function_exports))
2159 console::error("Failed parsing glx.tm!\n");
2163 process_func_protos("gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports, m_all_gl_ctypes, m_all_gl_categories, m_all_array_sizes);
2164 process_func_protos("glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_all_gl_ctypes, m_all_gl_categories, m_all_array_sizes);
2165 process_func_protos("glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_all_gl_ctypes, m_all_gl_categories, m_all_array_sizes);
2167 // -- Create the m_unique_ctype_enums table
2168 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2170 const gl_function_def &func = m_all_gl_funcs[i];
2172 m_unique_ctype_enums.insert(std::make_pair(func.m_return_ctype_enum, func.m_return_ctype));
2173 for (uint p = 0; p < func.m_params.size(); p++)
2174 m_unique_ctype_enums.insert(std::make_pair(func.m_params[p].m_ctype_enum, func.m_params[p].m_ctype));
2177 // -- Create the m_pointee_types table
2180 for (uint i = 0; i < whitelisted_funcs.size(); i++)
2182 int j = simple_replay_funcs.find(whitelisted_funcs[i]);
2184 printf("%s\n", whitelisted_funcs[i].get_ptr());
2189 for (gl_string_map::const_iterator it = m_unique_ctype_enums.begin(); it != m_unique_ctype_enums.end(); ++it)
2191 dynamic_string ctype(it->first.get_ptr());
2192 if (!ctype.ends_with("_PTR"))
2197 if (ctype.ends_with("_CONST"))
2200 if (m_unique_ctype_enums.find(ctype) != m_unique_ctype_enums.end())
2202 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype));
2206 dynamic_string ctype_without_const(ctype);
2207 int ofs = ctype_without_const.find_left("_CONST_");
2210 ctype_without_const.remove(ofs, 6);
2212 if (m_unique_ctype_enums.find(ctype_without_const) != m_unique_ctype_enums.end())
2214 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype_without_const));
2218 dynamic_string ctype_without_const_definition(it->second);
2220 int ptr_ofs = ctype_without_const_definition.find_right('*');
2222 ctype_without_const_definition.remove(ptr_ofs, 1);
2223 int const_ofs = ctype_without_const_definition.find_left("const");
2225 ctype_without_const_definition.remove(const_ofs, 5);
2226 ctype_without_const_definition.trim();
2228 printf("Introducing new ctype from ptr to pointee: %s %s\n", ctype_without_const.get_ptr(), ctype_without_const_definition.get_ptr());
2230 m_unique_ctype_enums.insert(std::make_pair(ctype_without_const, ctype_without_const_definition));
2232 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype_without_const));
2236 // these are NOT actually pointers, they are just big enough to hold pointers (like intptr_t)
2237 //m_pointee_types.insert(std::make_pair("VOGL_GLINTPTR", "VOGL_GLINT"));
2238 //m_pointee_types.insert(std::make_pair("VOGL_GLINTPTRARB", "VOGL_GLINT"));
2239 //m_pointee_types.insert(std::make_pair("VOGL_GLSIZEIPTR", "VOGL_GLSIZEI"));
2241 // -- Read the GL/GLX whitelisted and nullable funcs file
2242 //file_utils::read_text_file("gl_glx_whitelisted_funcs.txt", m_whitelisted_funcs, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintWarningMessages);
2243 if (!read_regex_function_array("gl_glx_whitelisted_funcs.txt", m_whitelisted_funcs))
2246 // -- Read the display list whitelist
2247 //file_utils::read_text_file("gl_glx_displaylist_whitelist.txt", m_whitelisted_displaylist_funcs, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintWarningMessages);
2248 if (!read_regex_function_array("gl_glx_displaylist_whitelist.txt", m_whitelisted_displaylist_funcs))
2251 //file_utils::read_text_file("gl_glx_nullable_funcs.txt", m_nullable_funcs, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintWarningMessages);
2252 if (!read_regex_function_array("gl_glx_nullable_funcs.txt", m_nullable_funcs))
2255 if (!read_regex_function_array("gl_glx_simple_replay_funcs.txt", m_simple_replay_funcs))
2258 update_whitelisted_funcs(m_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2260 m_whitelisted_funcs.sort();
2262 process_func_defs("gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, funcs_with_custom_array_size_macros, custom_return_param_array_size_macros, funcs_with_return_param_array_size_macros);
2263 process_func_defs("glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, funcs_with_custom_array_size_macros, custom_return_param_array_size_macros, funcs_with_return_param_array_size_macros);
2264 process_func_defs("glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, funcs_with_custom_array_size_macros, custom_return_param_array_size_macros, funcs_with_return_param_array_size_macros);
2266 uint cur_func_id = 0;
2267 create_array_size_macros("gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports, custom_array_size_macros, custom_array_size_macro_indices, custom_array_size_macro_names, cur_func_id);
2268 create_array_size_macros("glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, custom_array_size_macros, custom_array_size_macro_indices, custom_array_size_macro_names, cur_func_id);
2269 create_array_size_macros("glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, custom_array_size_macros, custom_array_size_macro_indices, custom_array_size_macro_names, cur_func_id);
2271 // -- Cross reference the GL spec vs. XML files, for validation
2272 if (!validate_functions(m_gl_xml_functions, m_all_gl_funcs, m_apitrace_gl_func_specs, m_gl_typemap, m_glx_typemap))
2274 console::error("Failed validating functions!\n");
2278 if (!init_gl_gets())
2284 bool func_regex(const char *pPattern) const
2287 if (!r.init(pPattern))
2289 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2294 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2296 if (r.full_match(m_all_gl_funcs[func_index].m_full_name.get_ptr()))
2298 const gl_function_def &func = m_all_gl_funcs[func_index];
2300 printf("%s ", func.m_return_ctype.get_ptr());
2301 printf("%s(", func.m_full_name.get_ptr());
2302 for (uint j = 0; j < func.m_params.size(); j++)
2304 printf("%s %s", func.m_params[j].m_ctype.get_ptr(), func.m_params[j].m_name.get_ptr());
2305 if (j != func.m_params.size() - 1)
2312 printf("Found %u results\n", t);
2317 bool param_regex(const char *pPattern) const
2320 if (!r.init(pPattern))
2322 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2327 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2329 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2331 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2333 if (r.full_match(func_def.m_params[param_index].m_name.get_ptr()))
2335 printf("%s %u %s\n", func_def.m_full_name.get_ptr(), param_index, func_def.m_params[param_index].m_name.get_ptr());
2340 printf("Found %u results\n", t);
2345 bool category_regex(const char *pPattern) const
2348 if (!r.init(pPattern))
2350 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2355 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2357 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2359 if (r.full_match(func_def.m_category.get_ptr()))
2361 printf("%s %s\n", func_def.m_full_name.get_ptr(), func_def.m_category.get_ptr());
2365 printf("Found %u results\n", t);
2370 bool ctype_regex(const char *pPattern) const
2373 if (!r.init(pPattern))
2375 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2380 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2382 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2384 if (r.full_match(func_def.m_return_ctype.get_ptr()))
2386 printf("%s return %s\n", func_def.m_full_name.get_ptr(), func_def.m_return_ctype.get_ptr());
2390 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2392 if (r.full_match(func_def.m_params[param_index].m_ctype.get_ptr()))
2394 printf("%s %u %s %s\n", func_def.m_full_name.get_ptr(), param_index, func_def.m_params[param_index].m_name.get_ptr(), func_def.m_params[param_index].m_ctype.get_ptr());
2399 printf("Found %u results\n", t);
2404 bool namespace_regex(const char *pPattern) const
2407 if (!r.init(pPattern))
2409 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2414 for (uint func_index = 0; func_index < m_apitrace_gl_func_specs.size(); func_index++)
2416 const apitrace_gl_func_def &func_def = m_apitrace_gl_func_specs[func_index];
2418 if (r.full_match(vogl_get_namespace_name(func_def.m_return_namespace)))
2420 printf("%s return %s\n", func_def.m_name.get_ptr(), vogl_get_namespace_name(func_def.m_return_namespace));
2424 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2426 const apitrace_gl_func_param_def ¶m = func_def.m_params[param_index];
2428 if (r.full_match(vogl_get_namespace_name(param.m_namespace)))
2430 printf("%s %u %s\n", func_def.m_name.get_ptr(), param_index, vogl_get_namespace_name(param.m_namespace));
2435 printf("Found %u results\n", t);
2440 bool dump_debug_files() const
2442 m_gl_enumerations.dump_to_text_file("dbg_enums.txt");
2443 m_glx_enumerations.dump_to_text_file("dbg_glx_enums.txt");
2444 m_glx_ext_enumerations.dump_to_text_file("dbg_glx_ext_enums.txt");
2446 // -- Dump the definitions for debugging
2447 m_gl_xml_functions.dump_to_file("dbg_gl_xml_funcs.txt");
2448 m_gl_funcs.dump_to_file("dbg_gl_funcs.txt");
2449 m_glx_funcs.dump_to_file("dbg_glx_funcs.txt");
2450 m_glxext_funcs.dump_to_file("dbg_glxext_funcs.txt");
2452 // -- Dump the spec typemap files, for debugging
2453 m_gl_typemap.dump_to_file("dbg_gl_typemap.txt");
2454 m_glx_typemap.dump_to_file("dbg_glx_typemap.txt");
2456 m_all_gl_funcs.dump_to_file("dbg_gl_all_funcs.txt");
2460 // Write a simple macro file line this:
2461 //GL_FUNC(OpenGL,true,GLenum,glGetError,(void),())
2462 //GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a))
2463 pFile = fopen_and_log("dbg_gl_glx_simple_func_macros.txt", "w");
2464 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2466 const gl_function_def &def = m_all_gl_funcs[i];
2467 if (def.m_return == "void")
2468 fprintf(pFile, "GL_FUNC_VOID(%s,%s,(%s),(%s))\n", def.get_lib_name(), def.m_full_name.get_ptr(), def.get_param_proto().get_ptr(), def.get_param_args().get_ptr());
2470 fprintf(pFile, "GL_FUNC(%s,%s,%s,(%s),(%s))\n", def.get_lib_name(), def.m_return_ctype.get_ptr(), def.m_full_name.get_ptr(), def.get_param_proto().get_ptr(), def.get_param_args().get_ptr());
2474 pFile = fopen_and_log("dbg_gl_glx_types.txt", "w");
2475 for (gl_string_set::const_iterator it = m_all_gl_ctypes.begin(); it != m_all_gl_ctypes.end(); ++it)
2476 vogl_fprintf(pFile, "%s\n", it->get_ptr());
2479 pFile = fopen_and_log("dbg_gl_glx_array_sizes.txt", "w");
2480 for (gl_string_set::const_iterator it = m_all_array_sizes.begin(); it != m_all_array_sizes.end(); ++it)
2481 vogl_fprintf(pFile, "%s\n", it->get_ptr());
2485 printf("--- Functions with custom array size macros:\n");
2486 for (uint i = 0; i < funcs_with_custom_array_size_macros.size(); i++)
2487 printf("%s\n", funcs_with_custom_array_size_macros[i].get_ptr());
2490 printf("--- Whitelisted functions with custom array size macros:\n");
2491 for (uint i = 0; i < funcs_with_custom_array_size_macros.size(); i++)
2493 if (scan_dynamic_string_array_for_string(m_whitelisted_funcs, funcs_with_custom_array_size_macros[i].get_ptr(), true) < 0)
2495 printf("%s\n", funcs_with_custom_array_size_macros[i].get_ptr());
2499 printf("--- All categories:\n");
2500 for (uint i = 0; i < m_unique_categories.size(); i++)
2501 printf("%s\n", m_unique_categories[i].get_ptr());
2504 // -- Write the final whitelist to a file for debugging
2505 file_utils::write_text_file("dbg_final_gl_glx_whitelisted_funcs.txt", m_whitelisted_funcs, true);
2507 VOGL_ASSERT(m_whitelisted_funcs.is_sorted());
2509 for (uint i = 0; i < m_unique_categories.size(); i++)
2511 dynamic_string_array missing_funcs;
2513 bool are_any_whitelisted = false;
2514 for (uint j = 0; j < m_all_gl_funcs.size(); j++)
2516 const gl_function_def &func = m_all_gl_funcs[j];
2517 if (func.m_category != m_unique_categories[i])
2520 bool is_whitelisted = m_whitelisted_funcs.find_sorted(func.m_full_name) >= 0;
2522 if (!is_whitelisted)
2523 missing_funcs.push_back(func.m_full_name);
2525 are_any_whitelisted = true;
2528 if (missing_funcs.size())
2530 printf("--- Non-whitelisted funcs for %s category %s:\n", are_any_whitelisted ? "partially supported" : "unsupported", m_unique_categories[i].get_ptr());
2531 for (uint j = 0; j < missing_funcs.size(); j++)
2532 printf("%s\n", missing_funcs[j].get_ptr());
2537 printf("--- Full support for category: %s\n", m_unique_categories[i].get_ptr());
2544 static FILE *fopen_and_log(const char *pFilename, const char *pMode)
2546 FILE *pFile = vogl_fopen(pFilename, pMode);
2549 console::error("Failed opening file \"%s\" for mode %s\n", pFilename, pMode);
2553 console::info("--- Generating \"%s\":\n", pFilename);
2557 bool generate() const
2559 if (!m_gl_enumerations.dump_to_definition_macro_file("gl_enums.inc", "GL"))
2561 if (!m_glx_enumerations.dump_to_definition_macro_file("glx_enums.inc", "GLX"))
2563 if (!m_glx_ext_enumerations.dump_to_definition_macro_file("glx_ext_enums.inc", "GLX"))
2566 if (!m_gl_enumerations.dump_to_description_macro_file("gl_enum_desc.inc", "GL", m_gl_typemap, m_glx_typemap))
2568 if (!m_glx_enumerations.dump_to_description_macro_file("glx_enum_desc.inc", "GLX", m_glx_typemap, m_gl_typemap))
2570 if (!m_glx_ext_enumerations.dump_to_description_macro_file("glx_ext_desc.inc", "GLX", m_glx_typemap, m_gl_typemap))
2573 // -- Generate the gl_glx_protos.inc include file
2574 FILE *pFile = fopen_and_log("gl_glx_protos.inc", "w");
2577 console::error("Failed creating file gl_glx_protos.inc!\n");
2580 dump_func_proto_macros(pFile, "gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports);
2581 dump_func_proto_macros(pFile, "glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports);
2582 dump_func_proto_macros(pFile, "glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports);
2583 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED\n");
2584 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED_VOID\n");
2585 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL\n");
2586 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL_VOID\n");
2587 vogl_fprintf(pFile, "#undef DEF_PROTO\n");
2588 vogl_fprintf(pFile, "#undef DEF_PROTO_VOID\n");
2591 // -- Generate the gl_glx_ctypes.inc include file
2592 pFile = fopen_and_log("gl_glx_ctypes.inc", "w");
2593 vogl_fprintf(pFile, "DEF_TYPE(VOGL_INVALID_CTYPE, int)\n");
2594 for (gl_string_map::const_iterator it = m_unique_ctype_enums.begin(); it != m_unique_ctype_enums.end(); ++it)
2595 vogl_fprintf(pFile, "DEF_TYPE(%s, %s)\n", it->first.get_ptr(), it->second.get_ptr());
2598 // -- Generate the gl_glx_ctypes_ptr_to_pointee.inc include file
2599 pFile = fopen_and_log("gl_glx_ctypes_ptr_to_pointee.inc", "w");
2600 for (gl_string_map::const_iterator it = m_pointee_types.begin(); it != m_pointee_types.end(); ++it)
2601 vogl_fprintf(pFile, "DEF_PTR_TO_POINTEE_TYPE(%s, %s)\n", it->first.get_ptr(), it->second.get_ptr());
2604 // -- Generate the gl_glx_simple_replay_funcs.inc simple replay funcs file, and update the whitelist
2605 generate_simple_replay_funcs(m_all_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2607 // -- Generate replayer helper macros
2608 generate_replay_func_load_macros(m_all_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2610 // -- Generate the gl_glx_func_defs.inc include file
2611 pFile = fopen_and_log("gl_glx_func_defs.inc", "w");
2614 console::error("Failed creating file gl_glx_func_defs.inc!\n");
2617 dump_inc_file_header(pFile);
2618 dump_func_def_macros(pFile, "gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs);
2619 dump_func_def_macros(pFile, "glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs);
2620 dump_func_def_macros(pFile, "glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs);
2621 dump_function_def_undef_macros(pFile);
2624 // -- Generate the gl_glx_func_return_param_array_size_macros.inc include file
2625 pFile = fopen_and_log("gl_glx_func_return_param_array_size_macros.inc", "w");
2628 console::error("Failed creating file gl_glx_func_return_param_array_size_macros.inc!\n");
2631 for (uint i = 0; i < custom_return_param_array_size_macros.size(); i++)
2633 dynamic_string macro_name(custom_return_param_array_size_macros[i]);
2634 int n = macro_name.find_left('(');
2636 macro_name.truncate(n);
2638 int num_params = custom_return_param_array_size_macros[i].count_char(',') + 1;
2640 dynamic_string params("(");
2641 for (int j = 0; j < num_params; j++)
2644 params.append_char(',');
2645 params.append_char((char)('a' + j));
2649 vogl_fprintf(pFile, "#ifndef %s\n", macro_name.get_ptr());
2650 vogl_fprintf(pFile, " #define %s%s -1\n", macro_name.get_ptr(), params.get_ptr());
2651 vogl_fprintf(pFile, "#endif\n");
2655 // -- Generate the gl_glx_func_descs.inc include file
2656 pFile = fopen_and_log("gl_glx_func_descs.inc", "w");
2657 dump_inc_file_header(pFile);
2658 dump_func_desc_macros(pFile, "gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_apitrace_gl_func_specs, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, m_whitelisted_displaylist_funcs);
2659 dump_func_desc_macros(pFile, "glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_apitrace_gl_func_specs, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, m_whitelisted_displaylist_funcs);
2660 dump_func_desc_macros(pFile, "glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_apitrace_gl_func_specs, m_gl_so_function_exports, m_whitelisted_funcs, m_nullable_funcs, m_whitelisted_displaylist_funcs);
2661 dump_function_def_undef_macros(pFile);
2664 pFile = fopen_and_log("gl_glx_categories.inc", "w");
2665 for (gl_string_set::const_iterator it = m_all_gl_categories.begin(); it != m_all_gl_categories.end(); ++it)
2666 vogl_fprintf(pFile, "DEF_CATEGORY(%s)\n", it->get_ptr());
2669 // -- Generate the gl_glx_array_size_macros.inc include file
2670 pFile = fopen_and_log("gl_glx_array_size_macros.inc", "w");
2671 for (gl_string_set::const_iterator it = custom_array_size_macros.begin(); it != custom_array_size_macros.end(); ++it)
2673 dynamic_string macro_name(it->get_ptr());
2674 macro_name.truncate(macro_name.find_left('('));
2675 vogl_fprintf(pFile, "#ifndef %s\n", macro_name.get_ptr());
2676 vogl_fprintf(pFile, " #define %s%s -1\n", macro_name.get_ptr(), DEF_FUNCTION_PROTO_PARAM_STR);
2677 vogl_fprintf(pFile, "#endif\n");
2681 // -- Generate the gl_glx_array_size_macros_validator.inc include file
2682 pFile = fopen_and_log("gl_glx_array_size_macros_validator.inc", "w");
2683 for (uint i = 0; i < custom_array_size_macro_indices.size(); i++)
2685 uint j = custom_array_size_macro_indices[i];
2686 uint func_index = j >> 16;
2687 uint param_index = j & 0xFFFF;
2688 VOGL_NOTE_UNUSED(param_index);
2690 const dynamic_string ¯o_name = custom_array_size_macro_names[i];
2692 vogl_fprintf(pFile, "#ifndef DEF_FUNCTION_CUSTOM_HANDLER_%s%s\n", g_lib_api_prefixes[m_all_gl_funcs[func_index].m_lib], m_all_gl_funcs[func_index].m_name.get_ptr());
2693 vogl_fprintf(pFile, " #ifdef %s\n", macro_name.get_ptr());
2694 vogl_fprintf(pFile, " VALIDATE_ARRAY_SIZE_MACRO_DEFINED(%s, 0x%08X)\n", macro_name.get_ptr(), custom_array_size_macro_indices[i]);
2695 vogl_fprintf(pFile, " #else\n");
2696 vogl_fprintf(pFile, " VALIDATE_ARRAY_SIZE_MACRO_NOT_DEFINED(%s, 0x%08X)\n", macro_name.get_ptr(), custom_array_size_macro_indices[i]);
2697 vogl_fprintf(pFile, " #endif\n");
2698 vogl_fprintf(pFile, "#endif\n");
2702 // -- Generate the gl_glx_custom_return_param_array_size_macro_validator.inc include file
2703 pFile = fopen_and_log("gl_glx_custom_return_param_array_size_macro_validator.inc", "w");
2704 for (uint i = 0; i < custom_return_param_array_size_macros.size(); i++)
2706 dynamic_string macro_name(custom_return_param_array_size_macros[i]);
2707 int n = macro_name.find_left('(');
2709 macro_name.truncate(n);
2711 vogl_fprintf(pFile, "#ifdef %s\n", macro_name.get_ptr());
2712 vogl_fprintf(pFile, " CUSTOM_FUNC_RETURN_PARAM_ARRAY_SIZE_HANDLER_DEFINED(%s, %s)\n", macro_name.get_ptr(), funcs_with_return_param_array_size_macros[i].get_ptr());
2713 vogl_fprintf(pFile, "#else\n");
2714 vogl_fprintf(pFile, " CUSTOM_FUNC_RETURN_PARAM_ARRAY_SIZE_HANDLER_NOT_DEFINED(%s, %s)\n", macro_name.get_ptr(), funcs_with_return_param_array_size_macros[i].get_ptr());
2715 vogl_fprintf(pFile, "#endif\n");
2719 // -- Generate the gl_glx_custom_func_handler_validator.inc include file
2720 pFile = fopen_and_log("gl_glx_custom_func_handler_validator.inc", "w");
2721 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2723 vogl_fprintf(pFile, "#ifdef DEF_FUNCTION_CUSTOM_HANDLER_%s%s\n", g_lib_api_prefixes[m_all_gl_funcs[i].m_lib], m_all_gl_funcs[i].m_name.get_ptr());
2724 vogl_fprintf(pFile, " CUSTOM_FUNC_HANDLER_DEFINED(%u)\n", i);
2725 vogl_fprintf(pFile, "#else\n");
2726 vogl_fprintf(pFile, " CUSTOM_FUNC_HANDLER_NOT_DEFINED(%u)\n", i);
2727 vogl_fprintf(pFile, "#endif\n");
2731 // -- Generate the gl_glx_array_size_macro_func_param_indices.inc include file
2732 pFile = fopen_and_log("gl_glx_array_size_macro_func_param_indices.inc", "w");
2733 for (uint i = 0; i < custom_array_size_macro_indices.size(); i++)
2736 vogl_fprintf(pFile, ",");
2737 vogl_fprintf(pFile, "0x%08X", custom_array_size_macro_indices[i]);
2739 vogl_fprintf(pFile, "\n");
2741 vogl_fprintf(pFile, "\n");
2744 if (!generate_gl_gets_inc_file())
2747 if (!generate_libvogltrace_export_script())
2754 //-----------------------------------------------------------------------------------------------------------------------
2756 //-----------------------------------------------------------------------------------------------------------------------
2759 static const struct gl_get_files
2761 const char *m_pFilename;
2763 } s_gl_get_files[] =
2765 { "gl10_gets.txt", 0x10 },
2766 { "gl15_gets.txt", 0x15 },
2767 { "gl21_gets.txt", 0x21 },
2768 { "gl33_gets.txt", 0x33 },
2769 { "gl40_gets.txt", 0x40 },
2770 { "gl41_gets.txt", 0x41 },
2771 { "gl42_gets.txt", 0x42 },
2772 { "gl43_gets.txt", 0x43 }
2775 for (uint file_iter = 0; file_iter < sizeof(s_gl_get_files) / sizeof(s_gl_get_files[0]); file_iter++)
2777 const char *pFilename = s_gl_get_files[file_iter].m_pFilename;
2779 // typedef vogl::hash_map<dynamic_string, gl_get> gl_get_hash_map;
2780 // gl_get_hash_map m_gl_gets;
2782 dynamic_string_array get_names;
2784 if (!file_utils::read_text_file(pFilename, get_names, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
2787 for (uint i = 0; i < get_names.size(); i++)
2789 if ((get_names[i].toupper().compare(get_names[i], true) != 0) || (get_names[i].contains(' ')))
2791 console::error("In file %s, enum name is invalid: \"%s\"\n", pFilename, get_names[i].get_ptr());
2795 gl_get_hash_map::insert_result ins_res(m_gl_gets.insert(get_names[i], gl_get()));
2796 gl_get &gl_get_obj = ins_res.first->second;
2797 gl_get_obj.m_name = get_names[i];
2798 gl_get_obj.m_min_vers = vogl::math::minimum(gl_get_obj.m_min_vers, s_gl_get_files[file_iter].m_vers);
2799 gl_get_obj.m_max_vers = vogl::math::maximum(gl_get_obj.m_max_vers, s_gl_get_files[file_iter].m_vers);
2803 //for (gl_get_hash_map::const_iterator it = m_gl_gets.begin(); it != m_gl_gets.end(); ++it)
2804 // printf("%s 0x%04X 0x%04X\n", it->first.get_ptr(), it->second.m_min_vers, it->second.m_max_vers);
2809 bool generate_libvogltrace_export_script() const
2812 // We're writing an anonymous version map on purpose, otherwise bad shit happens in some apps!
2822 const char *pFilename = "libvogltrace_linker_script.txt";
2823 cfile_stream export_script(pFilename, cDataStreamWritable);
2825 console::info("--- Generating \"%s\":\n", pFilename);
2827 export_script.puts("{\n");
2828 export_script.puts(" global:\n");
2830 for (uint i = 0; i < m_gl_so_function_exports.size(); i++)
2831 export_script.printf(" %s;\n", m_gl_so_function_exports[i].get_ptr());
2833 dynamic_string_array nongenerated_exports;
2834 file_utils::read_text_file("gl_glx_nongenerated_so_export_list.txt", nongenerated_exports, file_utils::cRTFPrintWarningMessages);
2836 for (uint i = 0; i < nongenerated_exports.size(); i++)
2837 export_script.printf(" %s;\n", nongenerated_exports[i].get_ptr());
2839 export_script.puts(" local:\n");
2840 export_script.puts(" *;\n");
2841 export_script.puts("};\n");
2846 //-----------------------------------------------------------------------------------------------------------------------
2847 // generate_gl_gets_inc_file
2848 //-----------------------------------------------------------------------------------------------------------------------
2849 bool generate_gl_gets_inc_file() const
2851 // Note: I used this to generate our first gl_gets.inc file, which then had to be hand edited.
2852 const char *pFilename = "gl_gets_approx.inc";
2853 cfile_stream gl_gets_inc(pFilename, cDataStreamWritable);
2855 if (!gl_gets_inc.is_opened())
2857 console::error("Failed creating file %s!\n", pFilename);
2861 console::info("--- Generating \"%s\":\n", pFilename);
2863 vogl::vector<gl_get> sorted_gets;
2864 for (gl_get_hash_map::const_iterator it = m_gl_gets.begin(); it != m_gl_gets.end(); ++it)
2865 sorted_gets.push_back(it->second);
2868 int prev_min_vers = -1;
2869 int prev_max_vers = -1;
2870 for (uint i = 0; i < sorted_gets.size(); i++)
2872 if ((prev_min_vers != static_cast<int>(sorted_gets[i].m_min_vers)) || (prev_max_vers != static_cast<int>(sorted_gets[i].m_max_vers)))
2874 gl_gets_inc.printf("// Start of version %u.%u - %u.%u\n", sorted_gets[i].m_min_vers >> 4, sorted_gets[i].m_min_vers & 0xF, sorted_gets[i].m_max_vers >> 4, sorted_gets[i].m_max_vers & 0xF);
2875 prev_min_vers = sorted_gets[i].m_min_vers;
2876 prev_max_vers = sorted_gets[i].m_max_vers;
2878 gl_gets_inc.printf("DEFINE_GL_GET(%s, 0x%04X, 0x%04X)\n", sorted_gets[i].m_name.get_ptr(), sorted_gets[i].m_min_vers, sorted_gets[i].m_max_vers);
2884 //-----------------------------------------------------------------------------------------------------------------------
2885 // ensure_gl_exports_are_defined
2886 //-----------------------------------------------------------------------------------------------------------------------
2887 bool ensure_gl_exports_are_defined(gl_function_specs &gl_funcs, const gl_function_specs &glx_funcs, const gl_function_specs &glxext_funcs)
2889 cfile_stream list_file("gl_glx_so_export_list.txt", cDataStreamReadable);
2890 if (!list_file.is_opened())
2893 dynamic_string line_str;
2894 while (list_file.get_remaining())
2896 if (!list_file.read_line(line_str))
2900 if (line_str.is_empty())
2903 dynamic_string func;
2904 const gl_function_specs *pSpecs = NULL;
2905 if (line_str.find_left("glX") == 0)
2907 func.set(line_str).right(3);
2908 pSpecs = &glx_funcs;
2910 else if (line_str.find_left("gl") == 0)
2912 func.set(line_str).right(2);
2918 console::warning("Unrecognized SO export: %s\n", line_str.get_ptr());
2922 const gl_function_def *pFunc = pSpecs->find(func.get_ptr());
2923 if ((!pFunc) && (pSpecs == &glx_funcs))
2925 pSpecs = &glxext_funcs;
2926 pFunc = pSpecs->find(func.get_ptr());
2931 if (func.ends_with("OES", true) || func.ends_with("x", true) || func.ends_with("NV", true) || func.ends_with("NVX") ||
2932 func.ends_with("SGI") || func.ends_with("EXT") || func.ends_with("X") || func.ends_with("xv") || func.ends_with("Autodesk") ||
2933 func.ends_with("WIN"))
2935 //console::warning("Skipping missing SO export: %s\n", line_str.get_ptr());
2939 console::warning("Can't find SO export in spec files: %s\n", line_str.get_ptr());
2943 //printf("Found %s\n", pFunc->m_name.get_ptr());
2949 //-----------------------------------------------------------------------------------------------------------------------
2950 // load_gl_so_function_export_list
2951 //-----------------------------------------------------------------------------------------------------------------------
2952 bool load_gl_so_function_export_list(const char *pFilename, dynamic_string_array &gl_so_function_exports)
2954 cfile_stream list_file(pFilename, cDataStreamReadable);
2955 if (!list_file.is_opened())
2958 dynamic_string line_str;
2959 while (list_file.get_remaining())
2961 if (!list_file.read_line(line_str))
2965 if (line_str.is_empty())
2968 gl_so_function_exports.push_back(line_str);
2971 gl_so_function_exports.sort();
2976 //-----------------------------------------------------------------------------------------------------------------------
2977 // translate_ctype_to_ctype_enum
2978 //-----------------------------------------------------------------------------------------------------------------------
2979 dynamic_string translate_ctype_to_ctype_enum(dynamic_string ctype)
2981 ctype.trim().toupper().replace("_", "");
2986 ctype.replace(" *", "*", true, &num_found);
2987 } while (num_found);
2991 ctype.replace(" ", " ", true, &num_found);
2992 } while (num_found);
2994 ctype.replace(" ", "_");
2995 ctype.replace("*", "_PTR");
2997 return "VOGL_" + ctype;
3000 //-----------------------------------------------------------------------------------------------------------------------
3002 //-----------------------------------------------------------------------------------------------------------------------
3003 bool determine_ctypes(const char *pFunc_prefix, gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap)
3005 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3007 gl_function_def &func = gl_funcs[func_index];
3009 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3011 if (func.m_return == "void")
3012 func.m_return_ctype = "void";
3015 const dynamic_string *pCType = typemap.find(func.m_return);
3017 pCType = alt_typemap.find(func.m_return);
3020 console::warning("Unable to map spec type %s\n", func.m_return.get_ptr());
3024 func.m_return_ctype = *pCType;
3026 func.m_return_ctype_enum = translate_ctype_to_ctype_enum(func.m_return_ctype);
3028 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3030 gl_function_param ¶m = func.m_params[param_index];
3032 const dynamic_string *pCType = typemap.find(param.m_type);
3034 pCType = alt_typemap.find(param.m_type);
3037 console::warning("Unable to map spec type %s\n", param.m_type.get_ptr());
3041 dynamic_string type_prefix;
3043 dynamic_string type_suffix("");
3044 if ((param.m_semantic == "array") || (param.m_semantic == "reference"))
3048 if (param.m_direction == "in")
3050 if (!pCType->ends_with("const"))
3051 type_prefix = "const ";
3055 dynamic_string full_ctype(cVarArg, "%s%s%s", type_prefix.get_ptr(), pCType->get_ptr(), type_suffix.get_ptr());
3057 param.m_ctype = full_ctype;
3058 param.m_ctype_enum = translate_ctype_to_ctype_enum(full_ctype);
3065 //-----------------------------------------------------------------------------------------------------------------------
3066 // get_func_proto_macro
3067 //-----------------------------------------------------------------------------------------------------------------------
3068 dynamic_string get_func_proto_macro(const char *pFunc_prefix, const gl_function_def &func, const dynamic_string_array &sorted_gl_so_function_exports) const
3070 dynamic_string proto;
3072 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3074 dynamic_string exported_param((func.m_return == "void") ? "DEF_PROTO_INTERNAL_VOID" : "DEF_PROTO_INTERNAL");
3075 int export_index = sorted_gl_so_function_exports.find_sorted(full_func_name);
3076 if (export_index >= 0)
3077 exported_param = (func.m_return == "void") ? "DEF_PROTO_EXPORTED_VOID" : "DEF_PROTO_EXPORTED";
3079 dynamic_string category(func.m_category.get_len() ? func.m_category.get_ptr() : "UNDEFINED");
3081 proto.format_append("( %s, %s, %s, %s, %u, ", exported_param.get_ptr(), category.get_ptr(), func.m_return_ctype.get_ptr(), func.m_return_ctype_enum.get_ptr(), func.m_params.size());
3083 proto.format_append("%s, ", full_func_name.get_ptr());
3085 proto.format_append("(");
3086 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3088 const gl_function_param ¶m = func.m_params[param_index];
3090 proto.format_append("%s%s%s", param.m_ctype.get_ptr(), param.m_ctype.ends_with("*") ? "" : " ", param.m_name.get_ptr());
3091 if (param_index != func.m_params.size() - 1)
3092 proto.format_append(", ");
3095 proto.format_append("), ");
3097 proto.format_append("(");
3098 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3100 proto.format_append("%s", func.m_params[param_index].m_name.get_ptr());
3101 if (param_index != func.m_params.size() - 1)
3102 proto.format_append(", ");
3105 proto.format_append(") )");
3110 //-----------------------------------------------------------------------------------------------------------------------
3111 // process_func_protos
3112 //-----------------------------------------------------------------------------------------------------------------------
3113 bool process_func_protos(
3114 const char *pFunc_prefix, const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const dynamic_string_array &sorted_gl_so_function_exports,
3115 gl_string_set &all_gl_ctypes, gl_string_set &all_gl_categories, gl_string_set &array_sizes)
3117 VOGL_NOTE_UNUSED(pFunc_prefix);
3118 VOGL_NOTE_UNUSED(typemap);
3119 VOGL_NOTE_UNUSED(alt_typemap);
3120 VOGL_NOTE_UNUSED(sorted_gl_so_function_exports);
3122 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3124 const gl_function_def &func = gl_funcs[func_index];
3126 all_gl_categories.insert(func.m_category);
3127 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3129 const gl_function_param ¶m = func.m_params[param_index];
3131 all_gl_ctypes.insert(param.m_ctype);
3132 array_sizes.insert(param.m_array_size);
3139 //-----------------------------------------------------------------------------------------------------------------------
3140 // dump_func_proto_macros
3141 //-----------------------------------------------------------------------------------------------------------------------
3142 bool dump_func_proto_macros(FILE *pFile, const char *pFunc_prefix, const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const dynamic_string_array &sorted_gl_so_function_exports) const
3144 VOGL_NOTE_UNUSED(typemap);
3145 VOGL_NOTE_UNUSED(alt_typemap);
3147 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3149 const gl_function_def &func = gl_funcs[func_index];
3151 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3153 vogl_fprintf(pFile, "%s%s\n", (func.m_return_ctype == "void") ? "DEF_PROTO_VOID" : "DEF_PROTO", func_proto.get_ptr());
3159 //-----------------------------------------------------------------------------------------------------------------------
3160 // func_param_translate_array_size
3161 //-----------------------------------------------------------------------------------------------------------------------
3162 dynamic_string func_param_translate_array_size(const char *pFunc_prefix, const gl_function_def &func, const gl_function_param ¶m, const dynamic_string &func_proto, bool *pCustom_macro_flag = NULL) const
3164 if (pCustom_macro_flag)
3165 *pCustom_macro_flag = false;
3167 if (param.m_array_size.begins_with("[") && param.m_array_size.ends_with("]"))
3169 dynamic_string array_size_param(param.m_array_size);
3170 array_size_param.mid(1, array_size_param.get_len() - 2);
3172 for (uint i = 0; i < func.m_params.size(); i++)
3173 if ((func.m_params[i].m_name == array_size_param) ||
3174 ((func.m_params[i].m_name + "*1") == array_size_param) ||
3175 ((func.m_params[i].m_name + "*2") == array_size_param) ||
3176 ((func.m_params[i].m_name + "*3") == array_size_param) ||
3177 ((func.m_params[i].m_name + "*4") == array_size_param) ||
3178 ((func.m_params[i].m_name + "*5") == array_size_param) ||
3179 ((func.m_params[i].m_name + "*6") == array_size_param) ||
3180 ((func.m_params[i].m_name + "*7") == array_size_param) ||
3181 ((func.m_params[i].m_name + "*8") == array_size_param) ||
3182 ((func.m_params[i].m_name + "*9") == array_size_param) ||
3183 ((func.m_params[i].m_name + "*10") == array_size_param) ||
3184 ((func.m_params[i].m_name + "*11") == array_size_param) ||
3185 ((func.m_params[i].m_name + "*12") == array_size_param) ||
3186 ((func.m_params[i].m_name + "*13") == array_size_param) ||
3187 ((func.m_params[i].m_name + "*14") == array_size_param) ||
3188 ((func.m_params[i].m_name + "*15") == array_size_param) ||
3189 ((func.m_params[i].m_name + "*16") == array_size_param))
3191 if (func.m_params[i].m_semantic == "value")
3192 return array_size_param;
3193 //else if (func.m_params[i].m_semantic == "reference")
3194 // return dynamic_string(cVarArg, "%s ? *%s : -2", array_size_param.get_ptr(), array_size_param.get_ptr());
3195 //else if ((func.m_params[i].m_semantic == "array") && (func.m_params[i].m_array_size == "[1]"))
3196 // return dynamic_string(cVarArg, "%s ? *%s : -2", array_size_param.get_ptr(), array_size_param.get_ptr());
3199 if (array_size_param == "0" || array_size_param == "1" || array_size_param == "2" ||
3200 array_size_param == "3" || array_size_param == "4" || array_size_param == "5" ||
3201 array_size_param == "6" || array_size_param == "7" || array_size_param == "8" ||
3202 array_size_param == "9" || array_size_param == "12" || array_size_param == "16")
3204 return array_size_param;
3207 if (array_size_param.begins_with("COMPSIZE(") && array_size_param.ends_with(")"))
3209 dynamic_string comp_size_param(array_size_param);
3210 comp_size_param.mid(9, comp_size_param.get_len() - 10);
3212 // each of these are assumed to be a GL enum
3213 if ((comp_size_param == "pname") || (comp_size_param == "attribute") ||
3214 (comp_size_param == "id") || //(comp_size_param == "buffer") ||
3215 (comp_size_param == "map") || //(comp_size_param == "name") ||
3216 (comp_size_param == "path") || (comp_size_param == "query") ||
3217 (comp_size_param == "target") || (comp_size_param == "type") ||
3218 (comp_size_param == "value"))
3219 return dynamic_string(cVarArg, "DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM(%s)", comp_size_param.get_ptr());
3221 // these might be wrong
3222 for (uint i = 0; i < func.m_params.size(); i++)
3223 if (((func.m_params[i].m_name + "*2") == comp_size_param) ||
3224 ((func.m_params[i].m_name + "*3") == comp_size_param) ||
3225 ((func.m_params[i].m_name + "*4") == comp_size_param))
3227 return dynamic_string(cVarArg, "DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM(%s)", comp_size_param.get_ptr());
3232 if (pCustom_macro_flag)
3233 *pCustom_macro_flag = true;
3235 dynamic_string custom_array_size(cVarArg, "DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_FUNC_%s%s_%s%s", pFunc_prefix, func.m_name.get_ptr(), param.m_name.get_ptr(), func_proto.get_ptr());
3236 return custom_array_size;
3239 //-----------------------------------------------------------------------------------------------------------------------
3240 // create_array_size_macros
3241 // TODO: use funcs_with_custom_array_size_macros[] vs. scanning for DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_FUNC_
3242 //-----------------------------------------------------------------------------------------------------------------------
3243 void create_array_size_macros(const char *pFunc_prefix, const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const dynamic_string_array &sorted_gl_so_function_exports,
3244 gl_string_set &custom_array_size_macros, vogl::vector<uint> &custom_array_size_macro_indices, dynamic_string_array &custom_array_size_macro_names, uint &cur_func_id) const
3246 VOGL_NOTE_UNUSED(typemap);
3247 VOGL_NOTE_UNUSED(alt_typemap);
3249 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3251 const gl_function_def &func = gl_funcs[func_index];
3253 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3255 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3257 const gl_function_param ¶m = func.m_params[param_index];
3259 if (param.m_semantic == "array")
3261 dynamic_string array_size_macro(func_param_translate_array_size(pFunc_prefix, func, param, func_proto));
3262 if (array_size_macro.begins_with("DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_FUNC_"))
3264 custom_array_size_macros.insert(array_size_macro);
3266 // oh god this is ugly
3267 dynamic_string macro_name(array_size_macro);
3268 int n = macro_name.find_left('(');
3270 macro_name.truncate(n);
3272 custom_array_size_macro_indices.push_back((cur_func_id << 16) | param_index);
3273 custom_array_size_macro_names.push_back(macro_name);
3282 //-----------------------------------------------------------------------------------------------------------------------
3283 // process_func_defs
3284 //-----------------------------------------------------------------------------------------------------------------------
3285 bool process_func_defs(const char *pFunc_prefix, const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const dynamic_string_array &sorted_gl_so_function_exports,
3286 const dynamic_string_array &whitelisted_funcs,
3287 const dynamic_string_array &nullable_funcs,
3288 dynamic_string_array &funcs_with_custom_array_size_macros,
3289 dynamic_string_array &custom_return_param_array_size_macros,
3290 dynamic_string_array &funcs_with_return_param_array_size_macros)
3292 VOGL_NOTE_UNUSED(typemap);
3293 VOGL_NOTE_UNUSED(alt_typemap);
3294 VOGL_NOTE_UNUSED(nullable_funcs);
3296 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3298 const gl_function_def &func = gl_funcs[func_index];
3300 dynamic_string full_func_name(func.m_full_name); //cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3302 bool is_in_whitelist = false;
3303 VOGL_NOTE_UNUSED(is_in_whitelist);
3304 for (uint i = 0; i < whitelisted_funcs.size(); i++)
3306 if (whitelisted_funcs[i] == full_func_name)
3308 is_in_whitelist = true;
3313 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3315 // TODO: This (func_has_custom_array_size_macros) is dead code
3316 bool func_has_custom_array_size_macros = false;
3318 dynamic_string func_params;
3320 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3322 const gl_function_param ¶m = func.m_params[param_index];
3324 func_params.append(param.m_name);
3325 if (param_index != (func.m_params.size() - 1))
3326 func_params.append(", ");
3329 if (func.m_return != "void")
3331 dynamic_string return_param_compute_array_size_macro_name(cVarArg, "DEF_FUNCTION_RETURN_PARAM_COMPUTE_ARRAY_SIZE_FUNC_%s(%s)", full_func_name.get_ptr(), func_params.get_ptr());
3333 custom_return_param_array_size_macros.push_back(return_param_compute_array_size_macro_name);
3334 funcs_with_return_param_array_size_macros.push_back(full_func_name);
3337 if (func_has_custom_array_size_macros)
3339 funcs_with_custom_array_size_macros.push_back(full_func_name);
3346 //-----------------------------------------------------------------------------------------------------------------------
3347 // dump_func_def_macros
3348 //-----------------------------------------------------------------------------------------------------------------------
3349 bool dump_func_def_macros(FILE *pFile, const char *pFunc_prefix, const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const dynamic_string_array &sorted_gl_so_function_exports,
3350 const dynamic_string_array &whitelisted_funcs,
3351 const dynamic_string_array &nullable_funcs) const
3353 VOGL_NOTE_UNUSED(typemap);
3354 VOGL_NOTE_UNUSED(alt_typemap);
3355 VOGL_NOTE_UNUSED(nullable_funcs);
3357 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3359 const gl_function_def &func = gl_funcs[func_index];
3361 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3363 bool is_in_whitelist = false;
3364 VOGL_NOTE_UNUSED(is_in_whitelist);
3365 for (uint i = 0; i < whitelisted_funcs.size(); i++)
3367 if (whitelisted_funcs[i] == full_func_name)
3369 is_in_whitelist = true;
3374 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3376 vogl_fprintf(pFile, "// %s Category: %s Vers: \"%s\" Deprecated: \"%s\" Profile: \"%s\"\n", full_func_name.get_ptr(), func.m_category.get_ptr(), func.m_version.get_ptr(), func.m_deprecated.get_ptr(), func.m_profile.get_ptr());
3378 vogl_fprintf(pFile, "#ifdef DEF_FUNCTION_CUSTOM_HANDLER_%s\n", full_func_name.get_ptr());
3380 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_HANDLER_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3381 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_HANDLER_%s\n", full_func_name.get_ptr());
3383 vogl_fprintf(pFile, "#else\n");
3385 vogl_fprintf(pFile, " DEF_FUNCTION_BEGIN%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3387 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s\n", full_func_name.get_ptr());
3388 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3389 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s\n", full_func_name.get_ptr());
3390 vogl_fprintf(pFile, " #endif\n");
3392 vogl_fprintf(pFile, " DEF_FUNCTION_INIT%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3394 bool func_has_custom_array_size_macros = false;
3396 dynamic_string func_params;
3398 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3400 const gl_function_param ¶m = func.m_params[param_index];
3402 func_params.append(param.m_name);
3403 if (param_index != (func.m_params.size() - 1))
3404 func_params.append(", ");
3406 if (param.m_direction != "in")
3409 if (param.m_semantic == "value")
3411 vogl_fprintf(pFile, " DEF_FUNCTION_INPUT_VALUE_PARAM( %u, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3413 else if (param.m_semantic == "array")
3415 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3416 vogl_fprintf(pFile, " DEF_FUNCTION_INPUT_ARRAY_PARAM( %u, %s, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr(), func_param_translate_array_size(pFunc_prefix, func, param, func_proto, &func_has_custom_array_size_macros).get_ptr());
3418 else if (param.m_semantic == "reference")
3420 vogl_fprintf(pFile, " DEF_FUNCTION_INPUT_REFERENCE_PARAM( %u, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3424 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_CALLER_%s\n", full_func_name.get_ptr());
3425 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_CALLER_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3426 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_CALLER_%s\n", full_func_name.get_ptr());
3428 vogl_fprintf(pFile, " #else\n");
3430 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_PROLOG_%s\n", full_func_name.get_ptr());
3431 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_PROLOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3432 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_PROLOG_%s\n", full_func_name.get_ptr());
3433 vogl_fprintf(pFile, " #endif\n");
3435 vogl_fprintf(pFile, " DEF_FUNCTION_CALL_GL%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3437 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_EPILOG_%s\n", full_func_name.get_ptr());
3438 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_EPILOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3439 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_EPILOG_%s\n", full_func_name.get_ptr());
3440 vogl_fprintf(pFile, " #endif\n");
3442 vogl_fprintf(pFile, " #endif\n");
3444 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3446 const gl_function_param ¶m = func.m_params[param_index];
3447 if (param.m_direction != "out")
3450 if (param.m_semantic == "value")
3452 vogl_fprintf(pFile, " DEF_FUNCTION_OUTPUT_VALUE_PARAM( %u, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3454 else if (param.m_semantic == "array")
3456 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3457 vogl_fprintf(pFile, " DEF_FUNCTION_OUTPUT_ARRAY_PARAM( %u, %s, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr(), func_param_translate_array_size(pFunc_prefix, func, param, func_proto, &func_has_custom_array_size_macros).get_ptr());
3459 else if (param.m_semantic == "reference")
3461 vogl_fprintf(pFile, " DEF_FUNCTION_OUTPUT_REFERENCE_PARAM( %u, %s, %s, %s, %s )\n", param_index, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3465 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s\n", full_func_name.get_ptr());
3466 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3467 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s\n", full_func_name.get_ptr());
3468 vogl_fprintf(pFile, " #endif\n");
3470 if (func.m_return != "void")
3472 //vogl_fprintf(pFile, " DEF_FUNCTION_RETURN_PARAM( %s, %s, %s, )\n", func.m_return.get_ptr(), func.m_return_ctype.get_ptr(), func.m_return_ctype_enum.get_ptr());
3473 dynamic_string return_param_compute_array_size_macro_name(cVarArg, "DEF_FUNCTION_RETURN_PARAM_COMPUTE_ARRAY_SIZE_FUNC_%s(%s)", full_func_name.get_ptr(), func_params.get_ptr());
3475 vogl_fprintf(pFile, " DEF_FUNCTION_RETURN_PARAM( %s, %s, %s, %s )\n", func.m_return.get_ptr(), func.m_return_ctype.get_ptr(), func.m_return_ctype_enum.get_ptr(), return_param_compute_array_size_macro_name.get_ptr());
3478 vogl_fprintf(pFile, " DEF_FUNCTION_END%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3480 vogl_fprintf(pFile, "#endif\n");
3481 vogl_fprintf(pFile, "\n");
3487 //-----------------------------------------------------------------------------------------------------------------------
3488 // dump_func_desc_macros
3489 //-----------------------------------------------------------------------------------------------------------------------
3490 bool dump_func_desc_macros(
3491 FILE *pFile, const char *pFunc_prefix,
3492 const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const apitrace_func_specs &apitrace_gl_func_specs,
3493 const dynamic_string_array &sorted_gl_so_function_exports, const dynamic_string_array &whitelisted_funcs, const dynamic_string_array &nullable_funcs, const dynamic_string_array &whitelisted_displaylists_funcs) const
3495 VOGL_NOTE_UNUSED(typemap);
3496 VOGL_NOTE_UNUSED(alt_typemap);
3498 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3500 const gl_function_def &func = gl_funcs[func_index];
3502 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3503 VOGL_ASSERT(full_func_name.compare(func.m_full_name, true) == 0);
3505 const apitrace_gl_func_def *pApitrace_func_def = apitrace_gl_func_specs.find(full_func_name.get_ptr());
3507 bool is_in_whitelist = whitelisted_funcs.find(full_func_name) != cInvalidIndex;
3508 bool is_nullable = nullable_funcs.find(full_func_name) != cInvalidIndex;
3510 bool is_whitelisted_for_displaylists = false;
3511 for (uint i = 0; i < whitelisted_displaylists_funcs.size(); i++)
3513 if (regexp_full_match(func.m_full_name.get_ptr(), whitelisted_displaylists_funcs[i].get_ptr()))
3515 is_whitelisted_for_displaylists = true;
3520 if (is_whitelisted_for_displaylists)
3522 if (func.m_notlistable)
3524 console::error("%s: Func's %s m_notlistable and is_whitelisted_for_displaylists flags are not compatible!\n", VOGL_METHOD_NAME, full_func_name.get_ptr());
3528 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3530 vogl_fprintf(pFile, "// %s Category: %s Vers: \"%s\" Deprecated: \"%s\" Profile: \"%s\"\n", full_func_name.get_ptr(), func.m_category.get_ptr(), func.m_version.get_ptr(), func.m_deprecated.get_ptr(), func.m_profile.get_ptr());
3532 vogl_fprintf(pFile, "DEF_FUNCTION_BEGIN%s\n", func_proto.get_ptr());
3534 vogl_namespace_t return_namespace = VOGL_NAMESPACE_UNKNOWN;
3535 if (pApitrace_func_def)
3536 return_namespace = pApitrace_func_def->m_return_namespace;
3538 vogl_fprintf(pFile, " DEF_FUNCTION_INFO( %i, %s, \"%s\", \"%s\", \"%s\", \"%s\", %s, %s, %s, %s )\n", (int)return_namespace, func.m_return.get_ptr(), func.m_category.get_ptr(), func.m_version.get_ptr(),
3539 func.m_profile.get_ptr(), func.m_deprecated.get_ptr(), is_in_whitelist ? "true" : "false", is_nullable ? "true" : "false", is_whitelisted_for_displaylists ? "true" : "false", !func.m_notlistable ? "true" : "false");
3541 if (func.m_params.size())
3543 vogl_fprintf(pFile, " DEF_FUNCTION_BEGIN_PARAMS\n");
3544 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3546 const gl_function_param ¶m = func.m_params[param_index];
3548 vogl_namespace_t param_namespace = VOGL_NAMESPACE_UNKNOWN;
3549 if (pApitrace_func_def)
3551 VOGL_ASSERT(param_index < pApitrace_func_def->m_params.size());
3552 if (param_index < pApitrace_func_def->m_params.size())
3553 param_namespace = pApitrace_func_def->m_params[param_index].m_namespace;
3556 dynamic_string dir(param.m_direction);
3559 if (param.m_semantic == "value")
3561 vogl_fprintf(pFile, " DEF_FUNCTION_%s_VALUE_PARAM( %i, %s, %s, %s, %s )\n", dir.get_ptr(), (int)param_namespace, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3563 else if (param.m_semantic == "array")
3565 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3566 vogl_fprintf(pFile, " DEF_FUNCTION_%s_ARRAY_PARAM( %i, %s, %s, %s, %s, %s )\n", dir.get_ptr(), (int)param_namespace, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr(), func_param_translate_array_size(pFunc_prefix, func, param, func_proto).get_ptr());
3568 else if (param.m_semantic == "reference")
3570 vogl_fprintf(pFile, " DEF_FUNCTION_%s_REFERENCE_PARAM( %i, %s, %s, %s, %s )\n", dir.get_ptr(), (int)param_namespace, param.m_type.get_ptr(), param.m_ctype.get_ptr(), param.m_ctype_enum.get_ptr(), param.m_name.get_ptr());
3573 vogl_fprintf(pFile, " DEF_FUNCTION_END_PARAMS\n");
3576 vogl_fprintf(pFile, " DEF_FUNCTION_RETURN( %s, %s, %s )\n", func.m_return.get_ptr(), func.m_return_ctype.get_ptr(), func.m_return_ctype_enum.get_ptr());
3578 vogl_fprintf(pFile, "DEF_FUNCTION_END%s\n", func_proto.get_ptr());
3580 vogl_fprintf(pFile, "\n");
3586 //-----------------------------------------------------------------------------------------------------------------------
3587 // dump_inc_file_header
3588 //-----------------------------------------------------------------------------------------------------------------------
3589 void dump_inc_file_header(FILE *pFile) const
3591 vogl_fprintf(pFile, "// Auto-generated by voglgen. Don't hand modify!\n\n");
3594 //-----------------------------------------------------------------------------------------------------------------------
3595 // dump_function_def_undef_macros
3596 //-----------------------------------------------------------------------------------------------------------------------
3597 void dump_function_def_undef_macros(FILE *pFile) const
3599 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED\n");
3600 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED_VOID\n");
3601 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL\n");
3602 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL_VOID\n");
3603 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN_PARAMS\n");
3604 vogl_fprintf(pFile, "#undef DEF_FUNCTION_REFERENCE_PARAM\n");
3605 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_VALUE_PARAM\n");
3606 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_ARRAY_PARAM\n");
3607 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_REFERENCE_PARAM\n");
3608 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUT_REFERENCE_PARAM\n");
3609 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUT_ARRAY_PARAM\n");
3610 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END_PARAMS\n");
3611 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN\n");
3612 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN_VOID\n");
3613 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INIT\n");
3614 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INIT_VOID\n");
3615 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_VALUE_PARAM\n");
3616 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_REFERENCE_PARAM\n");
3617 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_ARRAY_PARAM\n");
3618 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUTPUT_REFERENCE_PARAM\n");
3619 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUTPUT_ARRAY_PARAM\n");
3620 vogl_fprintf(pFile, "#undef DEF_FUNCTION_CALL_GL\n");
3621 vogl_fprintf(pFile, "#undef DEF_FUNCTION_CALL_GL_VOID\n");
3622 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END\n");
3623 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END_VOID\n");
3624 vogl_fprintf(pFile, "#undef DEF_FUNCTION_RETURN_PARAM\n");
3625 vogl_fprintf(pFile, "#undef DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM\n");
3626 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INFO\n");
3629 struct gl_type_alias_t
3631 const char *m_pName;
3632 const char *m_pAlias;
3635 //-----------------------------------------------------------------------------------------------------------------------
3637 //-----------------------------------------------------------------------------------------------------------------------
3638 static dynamic_string_array purify_gl_type(dynamic_string str)
3640 static const gl_type_alias_t g_gl_type_comparison_exception_table[] =
3642 { "__GLXextFuncPtr", "void *" },
3643 { "GLfunction", "void *" },
3644 { "GLuint*", "unsigned int *" },
3645 { "GLuint *", "unsigned int *" },
3646 { "GLuint", "unsigned int" },
3648 { "GLboolean", "bool" },
3649 { "GLvoid", "void" },
3650 { "int64_t", "int64_t" },
3651 { "GLint64", "int64_t" },
3652 { "GLvoid*", "void*" },
3653 { "handleARB", "GLhandleARB" },
3655 { "const GLubyte *", "const char *" },
3656 { "GLubyte *", "char *" },
3657 { "GLubyte*", "char *" },
3658 { "GLchar*", "char *" },
3659 { "GLchar* const", "char *" },
3660 { "const char *", "char *" },
3661 { "GLchar", "char" },
3662 { "void function()", "void *" },
3663 { "int32_t", "int" },
3664 { "GLclampf", "float" },
3665 { "GLfloat", "float" },
3666 { "GLclampd", "double" },
3667 { "GLdouble", "double" },
3668 { "GLsizei", "int" },
3669 { "int32_t *", "int *" },
3670 { "int64_t *", "int64_t *" },
3671 { "GLint64*", "int64_t *" },
3672 { "GLint32*", "int *" },
3673 { "GLint32 *", "int *" },
3674 { "const GLuint*", "const unsigned int *" },
3675 { "const GLuint *", "const unsigned int *" },
3676 { "GLuint32*", "unsigned int *" },
3677 { "GLuint32 *", "unsigned int *" },
3678 { "GLulong*", "unsigned long *" },
3679 { "GLint*", "int *" },
3680 { "GLint *", "int *" },
3681 { "const GLint *", "const int *" },
3682 { "const GLvoid *", "const void *" },
3683 { "const GLvoid*", "const void *" },
3684 { "GLvoid *", "void *" },
3685 { "GLvoid*", "void *" },
3686 { "GLchar *", "char *" },
3687 { "GLchar*", "char *" },
3688 { "const GLchar *", "const char *" },
3689 { "const GLchar*", "const char *" },
3690 { "GLcharARB *", "char *" },
3691 { "GLcharARB*", "char *" },
3692 { "const GLcharARB *", "const char *" },
3693 { "const GLcharARB*", "const char *" },
3694 { "uint *", "unsigned int *" },
3695 { "ulong", "unsigned long" },
3696 { "ulong *", "unsigned long *" },
3697 { "GLuint64", "unsigned int64_t" },
3698 { "GLuint64*", "unsigned int64_t *" },
3699 { "const GLuint64*", "const unsigned int64_t *" },
3700 { "GLuint64EXT", "unsigned int64_t" },
3701 { "const GLuint64EXT *", "const unsigned int64_t *" },
3702 { "GLuint64EXT *", "unsigned int64_t *" },
3703 { "GLint64", "int64_t" },
3704 { "GLint64*", "int64_t *" },
3705 { "const GLint64*", "const int64_t *" },
3706 { "GLint64EXT", "int64_t" },
3707 { "const GLint64EXT *", "const int64_t *" },
3708 { "GLint64EXT *", "int64_t *" },
3709 { "GLintptr", "int *" },
3710 { "GLintptrARB", "int *" },
3711 { "GLenum", "int" }, // Mapping GLenum->int is pushing it, but there are some extensions that don't agree on whether the param is GLenum or int.
3712 { "GLhalfNV", "GLhalf" },
3713 { "const GLhalfNV *", "const GLhalf *" },
3714 { "GLchar* const *", "char * const *" },
3715 { "GLchar **", "char **" },
3716 { "const GLfloat *", "const float *" },
3717 { "const GLdouble *", "const double *" },
3718 { "GLfloat *", "float *" },
3719 { "const GLfloat *", "const float *" },
3720 { "GLfloat*", "float *" },
3721 { "const GLfloat *", "const float *" },
3722 { "const GLfloat*", "const float *" },
3723 { "GLclampf *", "float *" },
3724 { "const GLclampf *", "const float *" },
3725 { "GLclampf*", "float *" },
3726 { "GLdouble *", "double *" },
3727 { "GLdouble*", "double *" },
3728 { "GLclampd *", "double *" },
3729 { "GLclampd*", "double *" },
3730 { "GLsizeiptrARB", "GLsizeiptr" },
3731 { "handleARB*", "GLhandleARB *" },
3732 { "const GLcharARB* *", "const char **" },
3733 { "GLchar * *", "const char **" },
3734 { "GLchar**", "const char **" },
3735 { "const GLchar* *", "const char **" },
3736 { "GLoint", "unsigned int" }, // Bad in scraped XML
3737 { "const GLchar * *", "const char **" },
3738 { "cl_context", "struct _cl_context *" }, // Correct in spec, bad in scraped XML.
3739 { "cl_event", "struct _cl_event *" }, // Correct in spec, bad in scraped XML.
3742 // See if the ctype can be aliased to a simpler, hopefully equivalent ctype.
3743 for (uint i = 0; i < VOGL_ARRAY_SIZE(g_gl_type_comparison_exception_table); i++)
3745 if (str == g_gl_type_comparison_exception_table[i].m_pName)
3747 str = g_gl_type_comparison_exception_table[i].m_pAlias;
3752 // Tokenize type string
3753 dynamic_string_array tokens;
3754 str.tokenize(" \t", tokens, true);
3756 // Kill all const crap, nobody seems to agree on it so screw it.
3757 for (int i = 0; i < static_cast<int>(tokens.size()); i++)
3759 if (tokens[i] == "const")
3766 // Seperate out trailing "*" chars into multiple tokens.
3767 dynamic_string ptr_str("*");
3769 for (int i = 0; i < static_cast<int>(tokens.size()); i++)
3773 if (tokens[i].get_len() == 1)
3776 int pointer_ofs = tokens[i].find_right('*');
3777 if (pointer_ofs < 0)
3780 tokens[i].truncate(pointer_ofs);
3781 tokens.insert(i + 1, ptr_str);
3788 //-----------------------------------------------------------------------------------------------------------------------
3789 // validate_functions
3790 //-----------------------------------------------------------------------------------------------------------------------
3791 bool validate_functions(const gl_function_specs &gl_xml_funcs, const gl_function_specs &gl_funcs, const apitrace_func_specs &apitrace_gl_funcs,
3792 const gl_types &primary_typemap, const gl_types &alt_typemap) const
3794 dynamic_string_array missing_funcs;
3796 uint total_skipped = 0;
3797 uint total_validated = 0;
3798 uint total_failures = 0;
3799 uint total_not_found = 0;
3801 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3803 const gl_function_def &func = gl_funcs[func_index];
3805 // Let's skip these guys, they are either bad in the XML and not worth fixing up the individual params in code, or they are totally uninteresting (SUN, OES),
3806 // or they have been manually validated to be correct in the .spec files.
3807 if ((func.m_name == "Uniform2ui") || (func.m_name == "Uniform3ui") || (func.m_name == "Uniform4ui") ||
3808 (func.m_name == "ProgramUniform2ui") || (func.m_name == "ProgramUniform3ui") || (func.m_name == "ProgramUniform4ui") ||
3809 (func.m_name == "ReplacementCodePointerSUN") || (func.m_name == "ClearDepthfOES") || (func.m_name == "QueryMatrixxOES") ||
3810 (func.m_name == "QueryMatrixxOES") || (func.m_name == "SendPbufferToVideoNV") || (func.m_name == "ReleaseVideoImageNV") ||
3811 (func.m_name == "BindVideoImageNV") || (func.m_name == "GetTransparentIndexSUN") ||
3812 (func.m_name == "GetIntegerui64i_vNV"))
3818 const gl_types *pPrimary_typemap = &primary_typemap;
3819 const gl_types *pAlt_typemap = &alt_typemap;
3820 if ((func.m_lib == cGLX) || (func.m_lib == cWGL))
3821 std::swap(pPrimary_typemap, pAlt_typemap);
3823 dynamic_string return_type;
3824 if (func.m_return == "void")
3826 return_type = "void";
3830 const dynamic_string *pCType = pPrimary_typemap->find(func.m_return);
3832 pCType = pAlt_typemap->find(func.m_return);
3835 console::warning("Unable to map spec type %s\n", func.m_return.get_ptr());
3839 return_type = *pCType;
3842 dynamic_string_array func_param_ctypes;
3844 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3846 const gl_function_param ¶m = func.m_params[param_index];
3848 const dynamic_string *pCType = pPrimary_typemap->find(param.m_type);
3850 pCType = pAlt_typemap->find(param.m_type);
3853 console::warning("Unable to map spec type %s\n", param.m_type.get_ptr());
3857 dynamic_string type_prefix;
3859 dynamic_string type_suffix("");
3860 if ((param.m_semantic == "array") || (param.m_semantic == "reference"))
3864 if (param.m_direction == "in")
3866 if (!pCType->ends_with("const"))
3867 type_prefix = "const ";
3871 dynamic_string full_ctype(cVarArg, "%s%s%s", type_prefix.get_ptr(), pCType->get_ptr(), type_suffix.get_ptr());
3873 func_param_ctypes.push_back(full_ctype);
3876 const apitrace_gl_func_def *pApitrace_func_def = apitrace_gl_funcs.find(func.m_full_name.get_ptr());
3877 if (pApitrace_func_def)
3879 if (pApitrace_func_def->m_return_gl_type != return_type)
3881 console::warning("Function %s return type mismatch vs. apitrace specs: spec: %s, apitrace: %s\n", func.m_full_name.get_ptr(), return_type.get_ptr(), pApitrace_func_def->m_return_gl_type.get_ptr());
3885 if (pApitrace_func_def->m_params.size() != func_param_ctypes.size())
3887 console::warning("Function %s has a different number of params vs. apitrace specs: spec: %u, apitrace: %u\n", func.m_full_name.get_ptr(), func_param_ctypes.size(), pApitrace_func_def->m_params.size());
3892 for (uint i = 0; i < func_param_ctypes.size(); i++)
3894 const apitrace_gl_func_param_def ¶m_def = pApitrace_func_def->m_params[i];
3896 dynamic_string apitrace_param_type(param_def.m_gl_type);
3898 dynamic_string_array purified_spec_ctype(purify_gl_type(func_param_ctypes[i]));
3899 dynamic_string_array purified_apitrace_ctype(purify_gl_type(apitrace_param_type));
3901 bool type_mismatch = purified_spec_ctype.size() != purified_apitrace_ctype.size();
3904 for (uint j = 0; j < purified_spec_ctype.size(); j++)
3906 if (purified_spec_ctype[j] != purified_apitrace_ctype[j])
3908 type_mismatch = true;
3916 console::warning("Function %s param %u, spec vs. apitrace type difference: spec: %s apitrace: %s\n", func.m_full_name.get_ptr(), i, func_param_ctypes[i].get_ptr(), apitrace_param_type.get_ptr());
3919 //printf(" { \"%s\", \"%s\" },\n", func_param_ctypes[i].get_ptr(), apitrace_param_type.get_ptr());
3926 //printf("Func not found in apitrace specs: %s\n", func.m_full_name.get_ptr());
3929 uint gl_xml_func_index;
3930 for (gl_xml_func_index = 0; gl_xml_func_index < gl_xml_funcs.size(); gl_xml_func_index++)
3932 if (gl_xml_funcs[gl_xml_func_index].m_lib != func.m_lib)
3935 dynamic_string gl_xml_func_name(gl_xml_funcs[gl_xml_func_index].m_name);
3937 if (gl_xml_func_name == func.m_name)
3941 if (gl_xml_func_index == gl_xml_funcs.size())
3943 dynamic_string suffix;
3944 if (func.m_name.ends_with("ARB", true) || func.m_name.ends_with("EXT", true))
3945 suffix.set(func.m_name).right(func.m_name.get_len() - 3);
3946 else if (func.m_name.ends_with("NV", true))
3947 suffix.set(func.m_name).right(func.m_name.get_len() - 2);
3949 if (suffix.get_len())
3951 for (gl_xml_func_index = 0; gl_xml_func_index < gl_xml_funcs.size(); gl_xml_func_index++)
3953 if (gl_xml_funcs[gl_xml_func_index].m_lib != func.m_lib)
3956 dynamic_string gl_xml_func_name(gl_xml_funcs[gl_xml_func_index].m_name);
3957 gl_xml_func_name += suffix;
3959 if (gl_xml_func_name == func.m_name)
3964 if (gl_xml_func_index == gl_xml_funcs.size())
3966 missing_funcs.push_back(func.m_name);
3972 const gl_function_def &xml_func = gl_xml_funcs[gl_xml_func_index];
3973 if (xml_func.m_params.size() != func.m_params.size())
3975 console::error("Function %s param number mismatch\n", func.m_name.get_ptr());
3980 dynamic_string_array purified_func_return(purify_gl_type(return_type));
3982 dynamic_string xml_func_return(xml_func.m_return);
3984 // XML exceptions (they where incorrect on the web, GLsync here makes no sense)
3985 if ((func.m_name == "FramebufferRenderbuffer") || (func.m_name == "FlushMappedBufferRange"))
3987 xml_func_return = "void";
3990 dynamic_string_array purified_xml_func_return(purify_gl_type(xml_func_return));
3992 if (purified_func_return.size() != purified_xml_func_return.size())
3994 console::warning("Function %s return type mismatch: \"%s\" != \"%s\"\n", func.m_name.get_ptr(), return_type.get_ptr(), xml_func_return.get_ptr());
3999 for (uint i = 0; i < purified_func_return.size(); i++)
4001 if (purified_func_return[i] != purified_xml_func_return[i])
4003 console::warning("Function %s return type mismatch: \"%s\" != \"%s\", param \"%s\" != \"%s\"\n", func.m_name.get_ptr(), return_type.get_ptr(), xml_func_return.get_ptr(), purified_func_return[i].get_ptr(), purified_xml_func_return[i].get_ptr());
4010 for (param_index = 0; param_index < func.m_params.size(); param_index++)
4012 dynamic_string param_type(func_param_ctypes[param_index]);
4013 dynamic_string xml_param_type(xml_func.m_params[param_index].m_type);
4015 // manual XML exceptions (incorrect on the web)
4016 if ((param_index == 4) && (func.m_name == "GetTransformFeedbackVarying"))
4018 xml_param_type = "GLsizei *";
4020 if ((param_index == 3) && (func.m_name == "GetActiveUniformBlockiv"))
4022 xml_param_type = "GLint *";
4024 if ((param_index == 1) && (func.m_name == "CreateContextAttribsARB"))
4026 xml_param_type = "GLXFBConfig";
4028 if ((param_index == 3) && (func.m_name == "ProgramNamedParameter4fvNV"))
4030 xml_param_type = "GLfloat *";
4032 if ((param_index == 3) && (func.m_name == "ProgramNamedParameter4dvNV"))
4034 xml_param_type = "GLdouble *";
4037 dynamic_string_array purified_param_type(purify_gl_type(param_type));
4038 dynamic_string_array purified_xml_param_type(purify_gl_type(xml_param_type));
4040 if (purified_param_type.size() != purified_xml_param_type.size())
4042 console::warning("Function %s param type mismatch: \"%s\" != \"%s\"\n", func.m_name.get_ptr(), param_type.get_ptr(), xml_param_type.get_ptr());
4047 for (uint j = 0; j < purified_param_type.size(); j++)
4049 if (purified_param_type[j] != purified_xml_param_type[j])
4051 console::warning("Function %s param type mismatch: \"%s\" != \"%s\", param \"%s\" != \"%s\"\n", func.m_name.get_ptr(),
4052 param_type.get_ptr(),
4053 xml_param_type.get_ptr(),
4054 purified_param_type[j].get_ptr(),
4055 purified_xml_param_type[j].get_ptr());
4066 printf("Results of spec vs. XML function validation:\n");
4067 printf("Total passed: %u\n", total_validated);
4068 printf("Total failures: %u\n", total_failures);
4069 printf("Total skipped: %u\n", total_skipped);
4070 printf("Total functions present in spec but missing in XML: %u\n", total_not_found);
4072 if (g_command_line_params.get_value_as_bool("verbose"))
4074 printf("\nMissing function list:\n");
4075 for (uint i = 0; i < missing_funcs.size(); i++)
4076 printf("%s\n", missing_funcs[i].get_ptr());
4078 printf("\nMissing function list excluding OES and vendor suffixes:\n");
4079 for (uint i = 0; i < missing_funcs.size(); i++)
4081 const dynamic_string &func = missing_funcs[i];
4084 for (j = 0; j < VOGL_ARRAY_SIZE(g_gl_vendor_suffixes); j++)
4085 if (func.ends_with(g_gl_vendor_suffixes[j], true))
4088 if (j < VOGL_ARRAY_SIZE(g_gl_vendor_suffixes))
4091 printf("%s\n", func.get_ptr());
4098 //-----------------------------------------------------------------------------------------------------------------------
4099 // update_whitelisted_funcs
4100 //-----------------------------------------------------------------------------------------------------------------------
4101 bool update_whitelisted_funcs(const gl_function_specs &gl_funcs, const gl_string_map &unique_ctype_enums, const gl_string_map &pointee_types, dynamic_string_array &whitelisted_funcs)
4103 VOGL_NOTE_UNUSED(unique_ctype_enums);
4104 VOGL_NOTE_UNUSED(pointee_types);
4106 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4108 vogl::vector<bool> used_flags(m_simple_replay_funcs.size());
4110 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4112 const gl_function_def &func_def = gl_funcs[func_index];
4113 dynamic_string full_func_name(func_def.m_full_name); //cVarArg, "%s%s", g_lib_api_prefixes[gl_funcs[func_index].m_lib], gl_funcs[func_index].m_name.get_ptr());
4116 for (i = 0; i < m_simple_replay_funcs.size(); i++)
4118 if (m_simple_replay_funcs[i].ends_with("*"))
4120 dynamic_string prefix(m_simple_replay_funcs[i]);
4121 prefix.left(prefix.get_len() - 1);
4122 if (full_func_name.begins_with(prefix.get_ptr()))
4127 if (full_func_name == m_simple_replay_funcs[i])
4132 if (i == m_simple_replay_funcs.size())
4135 VOGL_ASSERT(!used_flags[i]);
4136 used_flags[i] = true;
4138 if (whitelisted_funcs.find(full_func_name) < 0)
4140 console::printf("Adding simple GL replay func %s to func whitelist\n", full_func_name.get_ptr());
4141 whitelisted_funcs.push_back(full_func_name);
4145 console::warning("Simple GL replay func %s was already in the func whitelist\n", full_func_name.get_ptr());
4149 for (uint i = 0; i < m_simple_replay_funcs.size(); i++)
4152 console::warning("Simple replay func %s was not found/used\n", m_simple_replay_funcs[i].get_ptr());
4158 //-----------------------------------------------------------------------------------------------------------------------
4159 // generate_simple_replay_funcs
4160 //-----------------------------------------------------------------------------------------------------------------------
4161 bool generate_simple_replay_funcs(const gl_function_specs &gl_funcs, const gl_string_map &unique_ctype_enums, const gl_string_map &pointee_types, const dynamic_string_array &whitelisted_funcs) const
4163 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4165 console::info("--- Generating \"gl_glx_simple_replay_funcs.inc\":\n");
4167 FILE *pFile = vogl_fopen("gl_glx_simple_replay_funcs.inc", "w");
4170 console::error("Failed creating file gl_glx_simple_replay_funcs.inc\n");
4174 dump_inc_file_header(pFile);
4176 vogl::vector<bool> used_flags(m_simple_replay_funcs.size());
4178 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4180 const gl_function_def &func_def = gl_funcs[func_index];
4181 dynamic_string full_func_name(func_def.m_full_name); //cVarArg, "%s%s", g_lib_api_prefixes[gl_funcs[func_index].m_lib], gl_funcs[func_index].m_name.get_ptr());
4184 for (i = 0; i < m_simple_replay_funcs.size(); i++)
4186 if (m_simple_replay_funcs[i].ends_with("*"))
4188 dynamic_string prefix(m_simple_replay_funcs[i]);
4189 prefix.left(prefix.get_len() - 1);
4190 if (full_func_name.begins_with(prefix.get_ptr()))
4195 if (full_func_name == m_simple_replay_funcs[i])
4200 if (i == m_simple_replay_funcs.size())
4203 VOGL_ASSERT(!used_flags[i]);
4204 used_flags[i] = true;
4206 vogl_fprintf(pFile, "VOGL_SIMPLE_REPLAY_FUNC_BEGIN(%s, func_def.m_params.size())\n", full_func_name.get_ptr());
4208 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4210 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4212 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4214 gl_string_map::const_iterator it = pointee_types.find(func_def.m_params[param_index].m_ctype_enum);
4215 if (it == pointee_types.end())
4217 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4222 it = unique_ctype_enums.find(it->second);
4223 if (it == unique_ctype_enums.end())
4225 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4230 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(%s, %u)\n", it->second.get_ptr(), param_index);
4234 // TODO: Add expected size of buffer check
4235 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(%s, %u)\n", func_def.m_params[param_index].m_ctype.get_ptr(), param_index);
4239 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR\n");
4242 vogl_fprintf(pFile, "VOGL_SIMPLE_REPLAY_FUNC_END(%s)\n\n", full_func_name.get_ptr());
4250 //-----------------------------------------------------------------------------------------------------------------------
4251 // generate_replay_func_load_macros
4252 //-----------------------------------------------------------------------------------------------------------------------
4253 bool generate_replay_func_load_macros(const gl_function_specs &gl_funcs, const gl_string_map &unique_ctype_enums, const gl_string_map &pointee_types, const dynamic_string_array &whitelisted_funcs) const
4255 VOGL_NOTE_UNUSED(unique_ctype_enums);
4256 VOGL_NOTE_UNUSED(pointee_types);
4258 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4260 console::info("--- Generating \"gl_glx_replay_helper_macros.inc\":\n");
4262 FILE *pFile = vogl_fopen("gl_glx_replay_helper_macros.inc", "w");
4265 console::error("Failed creating file gl_glx_replay_helper_macros\n");
4269 dump_inc_file_header(pFile);
4271 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4273 const gl_function_def &func_def = gl_funcs[func_index];
4274 dynamic_string full_func_name(func_def.m_full_name); //cVarArg, "%s%s", g_lib_api_prefixes[gl_funcs[func_index].m_lib], gl_funcs[func_index].m_name.get_ptr());
4276 vogl_fprintf(pFile, "#define VOGL_REPLAY_LOAD_PARAMS_HELPER_%s %c\n", full_func_name.get_ptr(), func_def.m_params.size() ? '\\' : ' ');
4278 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4280 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4282 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4285 gl_string_map::const_iterator it = pointee_types.find(func_def.m_params[param_index].m_ctype_enum);
4286 if (it == pointee_types.end())
4288 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4293 it = unique_ctype_enums.find(it->second);
4294 if (it == unique_ctype_enums.end())
4296 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4302 dynamic_string const_str;
4303 if (!func_def.m_params[param_index].m_ctype.begins_with("const "))
4304 const_str = "const ";
4306 vogl_fprintf(pFile, " %s%s pTrace_%s = reinterpret_cast<%s%s>(trace_packet.get_param_client_memory_ptr(%u));", const_str.get_ptr(), func_def.m_params[param_index].m_ctype.get_ptr(), func_def.m_params[param_index].m_name.get_ptr(), const_str.get_ptr(), func_def.m_params[param_index].m_ctype.get_ptr(), param_index);
4310 vogl_fprintf(pFile, " %s %s = trace_packet.get_param_value<%s>(%u);", func_def.m_params[param_index].m_ctype.get_ptr(), func_def.m_params[param_index].m_name.get_ptr(), func_def.m_params[param_index].m_ctype.get_ptr(), param_index);
4314 vogl_fprintf(pFile, " \\\n");
4316 vogl_fprintf(pFile, "\n");
4319 vogl_fprintf(pFile, "\n");
4321 vogl_fprintf(pFile, "#define VOGL_REPLAY_CALL_GL_HELPER_%s GL_ENTRYPOINT(%s)(", full_func_name.get_ptr(), full_func_name.get_ptr());
4323 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4325 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4327 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4329 if (func_def.m_params[param_index].m_ctype_enum.begins_with("VOGL_CONST_"))
4330 vogl_fprintf(pFile, "pTrace_%s", func_def.m_params[param_index].m_name.get_ptr());
4332 vogl_fprintf(pFile, "pReplay_%s", func_def.m_params[param_index].m_name.get_ptr());
4336 vogl_fprintf(pFile, "%s", func_def.m_params[param_index].m_name.get_ptr());
4340 vogl_fprintf(pFile, ", ");
4343 vogl_fprintf(pFile, ")\n\n");
4351 //-----------------------------------------------------------------------------------------------------------------------
4352 // read_regex_function_array
4353 //-----------------------------------------------------------------------------------------------------------------------
4354 bool read_regex_function_array(const char *pFilename, dynamic_string_array &funcs)
4356 dynamic_string_array regex_func_patterns;
4358 if (!file_utils::read_text_file(pFilename, regex_func_patterns, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
4361 regex_func_patterns.unique(dynamic_string_equal_to_case_sensitive());
4363 vogl::vector<bool> used_flags(regex_func_patterns.size());
4365 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
4368 for (j = 0; j < regex_func_patterns.size(); j++)
4369 if (regexp_full_match(m_all_gl_funcs[i].m_full_name.get_ptr(), regex_func_patterns[j].get_ptr()))
4372 if (j < regex_func_patterns.size())
4374 funcs.push_back(m_all_gl_funcs[i].m_full_name);
4375 used_flags[j] = true;
4379 for (uint i = 0; i < used_flags.size(); i++)
4381 console::warning("%s: Regex pattern \"%s\" from file \"%s\" did not match any function names!\n", VOGL_METHOD_NAME, regex_func_patterns[i].get_ptr(), pFilename);
4387 //----------------------------------------------------------------------------------------------------------------------
4388 // init_command_line_params
4389 //----------------------------------------------------------------------------------------------------------------------
4390 static bool init_command_line_params(int argc, char *argv[])
4392 command_line_params::parse_config parse_cfg;
4393 parse_cfg.m_single_minus_params = true;
4394 parse_cfg.m_double_minus_params = true;
4396 if (!g_command_line_params.parse(get_command_line_params(argc, argv), VOGL_ARRAY_SIZE(g_command_line_param_descs), g_command_line_param_descs, parse_cfg))
4398 console::error("%s: Failed parsing command line parameters!\n", VOGL_FUNCTION_NAME);
4405 //-----------------------------------------------------------------------------------------------------------------------
4407 //-----------------------------------------------------------------------------------------------------------------------
4408 static bool check_for_option(int argc, char *argv[], const char *pOption)
4410 for (int i = 1; i < argc; i++)
4412 if ((argv[i][0] == '/') || (argv[i][0] == '-'))
4414 if (vogl_stricmp(&argv[i][1], pOption) == 0)
4421 //-----------------------------------------------------------------------------------------------------------------------
4423 //-----------------------------------------------------------------------------------------------------------------------
4424 static void print_title()
4426 console::printf("voglgen");
4427 console::printf(" %s Built %s, %s", vogl_is_x64() ? "x64" : "x86", __DATE__, __TIME__);
4428 #ifdef VOGL_BUILD_DEBUG
4429 console::printf(" DEBUG build");
4431 console::printf("\n");
4432 console::printf("Debugger present: %u\n", vogl_is_debugger_present());
4435 //-------------------------------------------------------------------------------------------------------------------------------
4437 //-------------------------------------------------------------------------------------------------------------------------------
4438 static int main_internal(int argc, char *argv[])
4440 VOGL_NOTE_UNUSED(argc);
4441 VOGL_NOTE_UNUSED(argv);
4445 colorized_console::init();
4446 colorized_console::set_exception_callback();
4448 if (check_for_option(argc, argv, "quiet"))
4449 console::disable_output();
4453 bool status = false;
4454 if (init_command_line_params(argc, argv))
4456 dynamic_string srcdir;
4458 if (g_command_line_params.get_value_as_string(srcdir, "srcdir"))
4460 printf("srcdir: '%s'\n", srcdir.get_ptr());
4461 chdir(srcdir.get_ptr());
4463 // If we can't find this text file, try the vogl/glspec dir.
4464 if (access("apitrace_gl_param_info.txt", F_OK) != 0)
4466 if (access("../../vogl/glspec/apitrace_gl_param_info.txt", F_OK) == 0)
4467 chdir("../../vogl/glspec");
4469 getcwd(cwd, sizeof(cwd));
4470 printf("Current working directory: %s\n\n", cwd);
4474 console::printf("---------------- Begin Generator Init\n");
4475 status = generator.init();
4476 console::printf("---------------- End Generator Init\n");
4480 dynamic_string regex_pattern;
4481 if (g_command_line_params.get_value_as_string(regex_pattern, "func_regex"))
4482 generator.func_regex(regex_pattern.get_ptr());
4483 else if (g_command_line_params.get_value_as_string(regex_pattern, "param_regex"))
4484 generator.param_regex(regex_pattern.get_ptr());
4485 else if (g_command_line_params.get_value_as_string(regex_pattern, "category_regex"))
4486 generator.category_regex(regex_pattern.get_ptr());
4487 else if (g_command_line_params.get_value_as_string(regex_pattern, "namespace_regex"))
4488 generator.namespace_regex(regex_pattern.get_ptr());
4489 else if (g_command_line_params.get_value_as_string(regex_pattern, "ctype_regex"))
4490 generator.ctype_regex(regex_pattern.get_ptr());
4493 console::printf("---------------- Begin Generate\n");
4494 status = generator.generate();
4495 console::printf("---------------- End Generate\n");
4497 if (status && g_command_line_params.get_value_as_bool("debug"))
4499 console::printf("---------------- Begin Debug Dump\n");
4500 generator.dump_debug_files();
4501 console::printf("---------------- End Debug Dump\n");
4508 console::error("voglgen FAILED!\n");
4510 console::printf("voglgen succeeded\n (to %s)\n", cwd);
4512 int exit_status = status ? EXIT_SUCCESS : EXIT_FAILURE;
4514 console::printf("%u warning(s), %u error(s)\n", console::get_total_messages(cWarningConsoleMessage), console::get_total_messages(cErrorConsoleMessage));
4516 console::printf("Exit status: %i\n", exit_status);
4518 colorized_console::deinit();
4520 vogl_print_heap_stats();
4522 return status ? EXIT_SUCCESS : EXIT_FAILURE;
4525 //-----------------------------------------------------------------------------------------------------------------------
4527 //-----------------------------------------------------------------------------------------------------------------------
4528 static void pause_and_wait(void)
4530 console::enable_output();
4532 console::message("\nPress a key to continue.\n");
4536 if (vogl_getch() != -1)
4541 //-----------------------------------------------------------------------------------------------------------------------
4543 //-----------------------------------------------------------------------------------------------------------------------
4544 int main(int argc, char *argv[])
4546 int status = EXIT_FAILURE;
4548 if (vogl_is_debugger_present())
4550 status = main_internal(argc, argv);
4557 status = main_internal(argc, argv);
4559 __except(EXCEPTION_EXECUTE_HANDLER)
4561 console::error("Uncached exception! voglgen command line tool failed!\n");
4564 status = main_internal(argc, argv);
4568 if (check_for_option(argc, argv, "pause"))
4570 if ((status == EXIT_FAILURE) || (console::get_total_messages(cErrorConsoleMessage)))