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 },
66 { "specdir", 1, false, NULL },
69 //-----------------------------------------------------------------------------------------------------------------------
71 //-------------------------------------------------------------------------------------------------------------------------------
80 static const char *g_lib_api_prefixes[] =
88 //-------------------------------------------------------------------------------------------------------------------------------
90 //-------------------------------------------------------------------------------------------------------------------------------
91 static const char *g_gl_vendor_suffixes[] =
93 "NV", "INTEL", "SGIS", "SGIX", "SUN", "NVX", "OES", "AMD", "ATI", "OES", "3DFX", "PGI", "INGR", "IBM"
96 //-------------------------------------------------------------------------------------------------------------------------------
97 // GL/GLX/WGL/etc. function specs
98 //-------------------------------------------------------------------------------------------------------------------------------
99 struct gl_function_param
101 dynamic_string m_name;
102 dynamic_string m_type;
103 dynamic_string m_ctype;
104 dynamic_string m_ctype_enum;
105 dynamic_string m_direction;
106 dynamic_string m_semantic; // array, reference, value
107 dynamic_string m_array_size;
120 m_ctype_enum.clear();
123 m_array_size.clear();
127 void print(FILE *pFile) const
129 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);
133 //-----------------------------------------------------------------------------------------------------------------------
134 // struct gl_function_def
135 //-----------------------------------------------------------------------------------------------------------------------
136 struct gl_function_def
138 dynamic_string m_name; // func name from spec file, without the gl/glx/wgl/etc. prefix
139 dynamic_string m_full_name; // full func name, with prefix
140 vogl::vector<dynamic_string> m_param_names;
142 dynamic_string m_return;
143 dynamic_string m_return_ctype;
144 dynamic_string m_return_ctype_enum;
146 vogl::vector<gl_function_param> m_params;
147 dynamic_string m_category;
148 dynamic_string m_version;
149 dynamic_string m_profile;
150 dynamic_string m_deprecated;
162 m_param_names.clear();
164 m_return_ctype.clear();
165 m_return_ctype_enum.clear();
170 m_deprecated.clear();
172 m_notlistable = false;
175 void print(FILE *pFile) const
177 vogl_fprintf(pFile, "Name: \"%s\", ParamNames: %u, Params: %u, Return: \"%s\", Category: \"%s\", Version: \"%s\", Profile: \"%s\", Deprecated: \"%s\", Lib: \"%s\" notlistable: %u\n",
179 m_param_names.size(),
182 m_category.get_ptr(),
185 m_deprecated.get_ptr(),
186 g_lib_api_prefixes[m_lib],
191 for (uint i = 0; i < m_params.size(); i++)
193 vogl_fprintf(pFile, " ");
194 m_params[i].print(pFile);
196 vogl_fprintf(pFile, "\n");
200 dynamic_string get_param_proto() const
202 dynamic_string proto;
203 for (uint param_index = 0; param_index < m_params.size(); param_index++)
205 const gl_function_param ¶m = m_params[param_index];
207 proto.format_append("%s%s%s", param.m_ctype.get_ptr(), param.m_ctype.ends_with("*") ? "" : " ", param.m_name.get_ptr());
208 if (param_index != m_params.size() - 1)
209 proto.format_append(", ");
214 dynamic_string get_param_args() const
216 dynamic_string proto;
217 for (uint param_index = 0; param_index < m_params.size(); param_index++)
219 proto.format_append("%s", m_params[param_index].m_name.get_ptr());
220 if (param_index != m_params.size() - 1)
221 proto.format_append(", ");
226 const char *get_lib_name() const
228 return g_lib_api_prefixes[m_lib];
232 typedef vogl::vector<gl_function_def> gl_function_def_vec;
234 //-----------------------------------------------------------------------------------------------------------------------
235 // struct gl_string_key_comparer
236 //-----------------------------------------------------------------------------------------------------------------------
237 struct gl_string_key_comparer
239 bool operator()(const dynamic_string &lhs, const dynamic_string &rhs) const
241 return lhs.compare(rhs, true) < 0;
245 typedef std::map<dynamic_string, dynamic_string, gl_string_key_comparer> gl_string_map;
246 typedef std::set<dynamic_string, gl_string_key_comparer> gl_string_set;
248 //-----------------------------------------------------------------------------------------------------------------------
249 // class gl_function_specs
250 //-----------------------------------------------------------------------------------------------------------------------
251 class gl_function_specs
263 gl_function_specs &operator+=(const gl_function_specs &other)
265 m_funcs.append(other.m_funcs);
271 return m_funcs.size();
274 const gl_function_def &operator[](uint i) const
279 gl_function_def &operator[](uint i)
284 const gl_function_def_vec &get_funcs_vec() const
289 gl_function_def_vec &get_funcs_vec()
294 int find_index(const char *pName) const
296 for (uint i = 0; i < m_funcs.size(); i++)
297 if (m_funcs[i].m_name.compare(pName, true) == 0)
303 const gl_function_def *find(const char *pName) const
305 for (uint i = 0; i < m_funcs.size(); i++)
306 if (m_funcs[i].m_name.compare(pName, true) == 0)
312 bool exists(const char *pName) const
314 return find(pName) != NULL;
317 void dump_to_file(const char *pFilename) const
319 FILE *pFile = vogl_fopen(pFilename, "w");
322 console::info("--- Dumping %u GL function specs to file \"%s\"\n", m_funcs.size(), pFilename);
324 vogl_fprintf(pFile, "Functions:\n");
325 for (uint i = 0; i < m_funcs.size(); i++)
327 m_funcs[i].print(pFile);
330 vogl_fprintf(pFile, "Categories:\n");
332 gl_string_set categories;
333 for (uint i = 0; i < m_funcs.size(); i++)
334 categories.insert(m_funcs[i].m_category);
336 for (gl_string_set::const_iterator it = categories.begin(); it != categories.end(); ++it)
337 vogl_fprintf(pFile, "\"%s\"\n", it->get_ptr());
343 bool parse_spec_file(const char *pSpec_filename, gl_lib_t default_gl_lib_type)
345 cfile_stream spec_file(pSpec_filename, cDataStreamReadable);
346 if (!spec_file.is_opened())
348 console::error("Unable to open file \"%s\"!\n", pSpec_filename);
352 dynamic_string cur_function_def;
353 vogl::vector<dynamic_string> cur_function_param_names;
354 gl_function_def *pCur_func_def = NULL;
356 uint max_num_params = 0;
357 uint total_functions = 0;
359 dynamic_string line_str;
360 while (spec_file.get_remaining())
362 if (!spec_file.read_line(line_str))
367 int comment_ofs = line_str.find_left('#');
368 if (comment_ofs >= 0)
370 line_str.truncate(comment_ofs);
374 if (line_str.is_empty())
377 if (line_str.find_left(':') >= 0)
379 cur_function_def.clear();
380 pCur_func_def = NULL;
381 cur_function_param_names.clear();
386 //printf("%s\n", line_str.get_ptr());
388 int paren_start = line_str.find_left('(');
389 int paren_end = line_str.find_right(')');
390 bool is_func_def = !vogl_isspace(line_str[0]) && ((paren_start >= 0) && (paren_end >= 0) && (paren_end > paren_start));
394 cur_function_def.set(line_str).left(paren_start).trim();
395 if (cur_function_def.is_empty())
397 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
400 cur_function_def = cur_function_def;
402 dynamic_string param_names(line_str);
403 param_names.mid(paren_start + 1, paren_end - paren_start - 1).trim();
405 cur_function_param_names.resize(0);
408 while (cur_ofs < (int)param_names.get_len())
410 int next_comma_ofs = param_names.find_left(',', cur_ofs);
412 dynamic_string cur_param_name(param_names);
413 if (next_comma_ofs < 0)
415 cur_param_name.right(cur_ofs).trim();
416 cur_ofs = param_names.get_len();
420 cur_param_name.mid(cur_ofs, next_comma_ofs - cur_ofs).trim();
421 cur_ofs = next_comma_ofs + 1;
424 if (!cur_param_name.is_empty())
426 cur_function_param_names.push_back(cur_param_name);
430 console::error("Empty parameter name: %s\n", line_str.get_ptr());
435 printf("Function: \"%s\", Params %u:\n", cur_function_def.get_ptr(), cur_function_param_names.size());
436 for (uint i = 0; i < cur_function_param_names.size(); i++)
438 printf(" %s\n", cur_function_param_names[i].get_ptr());
443 max_num_params = math::maximum(max_num_params, cur_function_param_names.size());
446 pCur_func_def = m_funcs.enlarge(1);
447 pCur_func_def->m_name = cur_function_def;
448 pCur_func_def->m_param_names = cur_function_param_names;
449 pCur_func_def->m_lib = default_gl_lib_type;
451 else if ((!cur_function_def.is_empty()) && pCur_func_def && vogl_isspace(line_str[0]))
453 vogl::vector<dynamic_string> func_attribute_tokens;
454 line_str.tokenize(" \t", func_attribute_tokens);
456 if (func_attribute_tokens.is_empty())
458 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
462 if (func_attribute_tokens[0] == "return")
464 if (func_attribute_tokens.size() != 2)
466 console::error("Expected return type on line: %s\n", line_str.get_ptr());
469 pCur_func_def->m_return = func_attribute_tokens[1];
471 else if (func_attribute_tokens[0] == "param")
473 if ((func_attribute_tokens.size() < 5) || (func_attribute_tokens.size() > 7))
475 console::error("Unexpected number of param tokens on line: %s\n", line_str.get_ptr());
479 if ((func_attribute_tokens[3] != "in") && (func_attribute_tokens[3] != "out"))
481 console::error("Unexpected param direction on line: %s\n", line_str.get_ptr());
485 if (func_attribute_tokens[4].find_left("array[") == 0)
487 // special case for glx.spec
488 int open_bracket = func_attribute_tokens[4].find_left('[');
489 int close_bracket = func_attribute_tokens[4].find_left(']');
490 if (open_bracket < close_bracket)
492 func_attribute_tokens.push_back(dynamic_string(func_attribute_tokens[4]));
493 func_attribute_tokens.back().right(open_bracket);
494 func_attribute_tokens[4].truncate(open_bracket);
498 if ((func_attribute_tokens[4] != "value") && (func_attribute_tokens[4] != "array") && (func_attribute_tokens[4] != "reference"))
500 console::error("Unexpected param semantic on line: %s\n", line_str.get_ptr());
504 gl_function_param *pParam = pCur_func_def->m_params.enlarge(1);
506 if (func_attribute_tokens.back() == "retained")
508 pParam->m_retained = true;
509 func_attribute_tokens.resize(func_attribute_tokens.size() - 1);
512 //param pname GetTextureParameter in value
513 //param params Float32 out array [COMPSIZE(pname)]
514 pParam->m_name = func_attribute_tokens[1];
515 pParam->m_type = func_attribute_tokens[2];
516 pParam->m_direction = func_attribute_tokens[3];
517 pParam->m_semantic = func_attribute_tokens[4];
518 if (pParam->m_semantic == "array")
520 if ((func_attribute_tokens[5][0] != '[') || (func_attribute_tokens[5].back() != ']'))
522 console::error("Unexpected array size on line: %s\n", line_str.get_ptr());
526 pParam->m_array_size = func_attribute_tokens[5];
529 int slash_ofs = pParam->m_array_size.find_left('/');
532 pParam->m_array_size.set_char(slash_ofs, ',');
535 else if (func_attribute_tokens.size() != 5)
537 console::error("Unexpected number of tokens on line: %s\n", line_str.get_ptr());
541 else if (func_attribute_tokens[0] == "category")
543 pCur_func_def->m_category = func_attribute_tokens[1];
545 if (pCur_func_def->m_category == "gl")
546 pCur_func_def->m_lib = cGL;
547 else if (pCur_func_def->m_category == "glX")
548 pCur_func_def->m_lib = cGLX;
549 else if (pCur_func_def->m_category == "wgl")
550 pCur_func_def->m_lib = cWGL;
551 else if (pCur_func_def->m_category == "glu")
552 pCur_func_def->m_lib = cGLU;
555 // lib is default_gl_lib_type
558 else if (func_attribute_tokens[0] == "version")
560 if (func_attribute_tokens.size() != 2)
562 console::error("Invalid version param on line: %s\n", line_str.get_ptr());
566 pCur_func_def->m_version = func_attribute_tokens[1];
568 else if (func_attribute_tokens[0] == "profile")
570 if (func_attribute_tokens.size() != 2)
572 console::error("Invalid profile param on line: %s\n", line_str.get_ptr());
576 pCur_func_def->m_profile = func_attribute_tokens[1];
578 else if (func_attribute_tokens[0] == "deprecated")
580 if (func_attribute_tokens.size() != 2)
582 console::error("Invalid deprecated param on line: %s\n", line_str.get_ptr());
586 pCur_func_def->m_deprecated = func_attribute_tokens[1];
588 else if (func_attribute_tokens[0] == "dlflags")
590 if (func_attribute_tokens.size() != 2)
592 console::error("Invalid dlflags on line: %s\n", line_str.get_ptr());
596 if ((func_attribute_tokens[1] != "notlistable") && (func_attribute_tokens[1] != "handcode") && (func_attribute_tokens[1] != "prepad"))
598 console::error("Unrecognized dlflags on line: %s\n", line_str.get_ptr());
602 pCur_func_def->m_notlistable = (func_attribute_tokens[1] == "notlistable");
608 console::error("Skipping unrecognized line: %s\n", line_str.get_ptr());
612 for (uint i = 0; i < m_funcs.size(); i++)
614 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());
620 bool parse_gl_xml_file(const char *pFilename)
622 TiXmlDocument gl_xml;
623 if (!gl_xml.LoadFile(pFilename))
625 console::error("Failed loading %s!\n", pFilename);
629 const TiXmlElement *pRoot = gl_xml.RootElement();
630 const char *pName = pRoot->Attribute("name");
631 if ((!pName) || (strcmp(pName, "gl")))
633 console::error("Invalid root element in %s!\n", pFilename);
637 const TiXmlElement *pLibraries = pRoot->FirstChildElement("libraries");
638 const TiXmlElement *pExtensions = pRoot->FirstChildElement("extensions");
639 if ((!pLibraries) || (!pExtensions))
641 console::error("Couldn't find libraries and/or extensions elements in %s!\n", pFilename);
645 const TiXmlElement *pLibrary = pLibraries->FirstChildElement();
648 const char *pName = pLibrary->Attribute("name");
651 if (!parse_gl_xml_function_defs(pFilename, pName, pLibrary->FirstChildElement()))
655 pLibrary = pLibrary->NextSiblingElement();
658 const TiXmlElement *pCur_extension = pExtensions->FirstChildElement();
659 while (pCur_extension)
661 const char *pExt_name = pCur_extension->Attribute("name");
664 console::error("Couldn't find extension name attribute in %s!\n", pFilename);
668 if (!parse_gl_xml_function_defs(pFilename, pExt_name, pCur_extension->FirstChildElement()))
671 pCur_extension = pCur_extension->NextSiblingElement();
678 gl_function_def_vec m_funcs;
680 bool parse_gl_xml_function_defs(const char *pFilename, const char *pCategory, const TiXmlElement *pFunctions)
684 if ((pFunctions->Value()) && (strcmp(pFunctions->Value(), "functions") == 0))
686 const TiXmlElement *pFunction = pFunctions->FirstChildElement();
689 if ((pFunction->Value()) && (strcmp(pFunction->Value(), "function") == 0))
691 const char *pType = pFunction->Attribute("type");
692 const char *pName = pFunction->Attribute("name");
693 if ((!pType) || (!pName))
695 console::error("Expected function name and type in file %s\n", pFilename);
699 gl_function_def gl_func;
702 gl_func.m_full_name = pName;
703 gl_func.m_name = pName;
705 if (gl_func.m_name.begins_with("glX", true))
707 gl_func.m_name.right(3);
708 gl_func.m_lib = cGLX;
710 else if (gl_func.m_name.begins_with("glu", true))
712 gl_func.m_name.right(3);
713 gl_func.m_lib = cGLU;
715 else if (gl_func.m_name.begins_with("wgl", true))
717 gl_func.m_name.right(3);
718 gl_func.m_lib = cWGL;
720 else if (gl_func.m_name.begins_with("gl", true))
722 gl_func.m_name.right(2);
727 //console::warning("Unknown function prefix from XML, assuming \"gl\": %s\n", gl_func.m_name.get_ptr());
729 gl_func.m_full_name.format("%s%s", "gl", pName);
732 gl_func.m_category = pCategory;
733 gl_func.m_return = pType;
735 const TiXmlElement *pParams = pFunction->FirstChildElement();
738 if (strcmp(pParams->Value(), "param") == 0)
740 const char *pParam_type = pParams->Attribute("type");
741 const char *pParam_name = pParams->Attribute("name");
742 if ((!pParam_type) || (!pParam_name))
744 console::error("Expected parameter type and name in file %s\n", pFilename);
748 gl_function_param param;
750 param.m_name = pParam_name;
751 param.m_type = pParam_type;
752 gl_func.m_params.push_back(param);
754 pParams = pParams->NextSiblingElement();
757 if ((gl_func.m_params.size() == 1) && (gl_func.m_params[0].m_type == "") && (gl_func.m_params[0].m_name == "void"))
758 gl_func.m_params.resize(0);
760 m_funcs.push_back(gl_func);
763 pFunction = pFunction->NextSiblingElement();
767 pFunctions = pFunctions->NextSiblingElement();
774 //-----------------------------------------------------------------------------------------------------------------------
775 // apitrace glapi.py parsing
776 //-----------------------------------------------------------------------------------------------------------------------
779 const char *m_pSpec_return_type;
780 const char *m_pApitrace_return_type;
781 vogl_namespace_t m_namespace;
782 } g_apitrace_return_type_aliases[] =
784 { "void", "Void", VOGL_NAMESPACE_INVALID },
785 { "GLenum", "GLenum_error", VOGL_NAMESPACE_INVALID },
786 { "const GLubyte *", "String(Const(GLubyte))", VOGL_NAMESPACE_INVALID },
787 { "GLuint", "Handle(\"list\", GLuint, \"range\")", VOGL_NAMESPACE_LISTS },
788 { "GLint", "Alias(\"GLint\", GLenum)", VOGL_NAMESPACE_INVALID },
789 { "GLvoid*", "GLmap", VOGL_NAMESPACE_INVALID },
790 { "GLuint", "GLprogram", VOGL_NAMESPACE_PROGRAMS },
791 { "GLuint", "GLshader", VOGL_NAMESPACE_SHADERS },
792 { "GLint", "GLlocation", VOGL_NAMESPACE_LOCATIONS },
793 { "GLubyte *", "String(Const(GLubyte))", VOGL_NAMESPACE_INVALID },
794 { "GLint", "GLlocationARB", VOGL_NAMESPACE_LOCATIONS },
795 { "GLuint", "Handle(\"fragmentShaderATI\", GLuint, \"range\")", VOGL_NAMESPACE_FRAGMENT_SHADER_ATI }
798 const uint APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE = sizeof(g_apitrace_return_type_aliases) / sizeof(g_apitrace_return_type_aliases[0]);
800 //-----------------------------------------------------------------------------------------------------------------------
801 // g_apitrace_param_type_aliases array
802 //-----------------------------------------------------------------------------------------------------------------------
806 const char *m_pSpec_type;
807 const char *m_pApitrace_type;
808 } g_apitrace_param_type_aliases[] =
810 { "GLbitfield", "GLbitfield_access" },
811 { "GLbitfield", "GLbitfield_attrib" },
812 { "GLbitfield", "GLbitfield_barrier" },
813 { "GLbitfield", "GLbitfield_client_attrib" },
814 { "GLbitfield", "GLbitfield_shader" },
815 { "GLbitfield", "GLbitfield_sync_flush" },
816 { "GLuint", "GLpipeline" },
817 { "GLuint", "GLarray" },
818 { "GLuint", "GLarrayAPPLE" },
819 { "GLuint", "GLbuffer" },
820 { "GLuint", "GLfeedback" },
821 { "GLuint", "GLfence" },
822 { "GLuint", "GLframebuffer" },
823 { "GLuint", "GLpipeline" },
824 { "GLuint", "GLprogramARB" },
825 { "GLuint", "GLquery" },
826 { "GLuint", "GLrenderbuffer" },
827 { "GLuint", "GLsampler" },
828 { "GLuint", "GLtexture" },
829 { "GLuint", "GLarray" },
830 { "GLuint", "GLarrayAPPLE" },
831 { "GLuint", "GLbuffer" },
832 { "GLuint", "GLfeedback" },
833 { "GLuint", "GLfence" },
834 { "GLuint", "GLfragmentShaderATI" },
835 { "GLuint", "GLframebuffer" },
836 { "GLuint", "GLlist" },
837 { "GLuint", "GLpipeline" },
838 { "GLuint", "GLprogram" },
839 { "GLuint", "GLprogramARB" },
840 { "GLuint", "GLquery" },
841 { "GLuint", "GLrenderbuffer" },
842 { "GLuint", "GLsampler" },
843 { "GLuint", "GLshader" },
844 { "GLuint", "GLtexture" },
845 { "GLvoid *", "GLpointer" },
846 { "GLvoid", "GLIndexBuffer" },
847 { "GLchar *", "GLstring" },
848 { "const GLvoid *", "GLpointerConst" },
849 { "GLhalf", "GLhalfNV" },
850 { "const GLchar *", "GLstringConst" },
851 { "const GLchar *", "GLstringConstARB" },
852 { "GLchar *", "GLstringARB" },
853 { "GLchar", "GLcharARB" },
854 { "GLint", "GLlocation" },
855 { "GLint", "GLlocationARB" },
856 { "GLenum", "GLenum_int" },
857 { "GLint", "size_bgra" },
858 { "GLenum", "GLenum_mode" },
861 static const uint APITRACE_PARAM_TYPE_ALIASES_ARRAY_SIZE = sizeof(g_apitrace_param_type_aliases) / sizeof(g_apitrace_param_type_aliases[0]);
863 //-----------------------------------------------------------------------------------------------------------------------
864 // struct apitrace_gl_func_param_def
865 //-----------------------------------------------------------------------------------------------------------------------
866 struct apitrace_gl_func_param_def
868 apitrace_gl_func_param_def()
879 m_array_count_str.clear();
880 m_index_count_str.clear();
881 m_string_count_str.clear();
882 m_index_type_str.clear();
885 m_is_pointer = false;
890 m_is_index_buffer = false;
892 m_is_opaque_ctype = false;
895 dynamic_string m_name;
896 dynamic_string m_type;
897 dynamic_string m_gl_type; // actual C type (but without const stuff)
898 vogl_namespace_t m_namespace;
900 dynamic_string m_array_count_str;
901 dynamic_string m_index_count_str;
902 dynamic_string m_string_count_str;
903 dynamic_string m_index_type_str;
911 bool m_is_index_buffer;
913 bool m_is_opaque_ctype;
916 typedef vogl::vector<apitrace_gl_func_param_def> apitrace_gl_func_param_def_array;
918 //-----------------------------------------------------------------------------------------------------------------------
919 // struct apitrace_gl_func_def
920 //-----------------------------------------------------------------------------------------------------------------------
921 struct apitrace_gl_func_def
923 apitrace_gl_func_def()
931 m_return_type.clear();
932 m_return_gl_type.clear();
933 m_has_side_effects = false;
937 dynamic_string m_name;
938 dynamic_string m_return_type;
939 dynamic_string m_return_gl_type; // actual C type (but without const stuff)
940 vogl_namespace_t m_return_namespace;
942 bool m_has_side_effects;
943 apitrace_gl_func_param_def_array m_params;
946 typedef vogl::vector<apitrace_gl_func_def> apitrace_gl_func_def_array;
948 //-----------------------------------------------------------------------------------------------------------------------
949 // class apitrace_func_specs
950 //-----------------------------------------------------------------------------------------------------------------------
952 //#define APITRACE_FUNC_SPECS_DEBUG
954 class apitrace_func_specs
957 apitrace_func_specs()
968 return m_funcs.size();
971 const apitrace_gl_func_def &operator[](uint i) const
976 apitrace_gl_func_def &operator[](uint i)
981 const apitrace_gl_func_def_array &get_funcs_vec() const
986 apitrace_gl_func_def_array &get_funcs_vec()
991 int find_index(const char *pName) const
993 for (uint i = 0; i < m_funcs.size(); i++)
994 if (m_funcs[i].m_name.compare(pName, true) == 0)
1000 const apitrace_gl_func_def *find(const char *pName) const
1002 for (uint i = 0; i < m_funcs.size(); i++)
1003 if (m_funcs[i].m_name.compare(pName, true) == 0)
1009 bool exists(const char *pName) const
1011 return find(pName) != NULL;
1014 // Yes this guy is ugly, but it's simple and works on the unmodified Python source glapi.py from apitrace.
1015 // glapi.py was automatically generated, then hand edited. It contains a lot of useful type and array size info, but is still
1016 // incomplete (see glReadPixels() for example, which is missing its array size).
1017 bool parse(const char *pFilename = "apitrace_gl_param_info.txt")
1021 dynamic_string_array param_info_file;
1022 if (!file_utils::read_text_file(pFilename, param_info_file, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
1025 dynamic_string_array unique_types;
1026 dynamic_string_array unique_array_counts;
1028 for (uint line_index = 0; line_index < param_info_file.size(); line_index++)
1030 const dynamic_string &orig_line(param_info_file[line_index]);
1031 dynamic_string line(orig_line);
1033 if (line.begins_with("#"))
1036 int comment_ofs = line.find_right('#');
1037 if (comment_ofs >= 0)
1038 line.left(comment_ofs).trim();
1040 if (!line.begins_with("GlFunction("))
1041 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1043 line.replace("GlFunction(", "", true, NULL, 1);
1045 if (line.ends_with(","))
1048 if (!line.ends_with(")"))
1049 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1051 dynamic_string return_type;
1053 int first_comma = line.find_left(',');
1054 if (first_comma < 0)
1055 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1057 int first_paren = line.find_left('(');
1058 if ((first_paren >= 0) && (first_paren < first_comma))
1060 int matching_paren = find_matching_paren(line, first_paren);
1061 if (matching_paren < 0)
1062 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1064 return_type = dynamic_string(line).left(matching_paren + 1);
1065 line.right(matching_paren + 1).trim();
1066 if (!line.begins_with(","))
1067 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1069 line.right(1).trim();
1073 return_type = dynamic_string(line).left(first_comma);
1074 line.right(first_comma + 1).trim();
1077 if (!line.begins_with("\""))
1078 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1080 int end_quote_ofs = line.find_left('\"', 1);
1081 if (end_quote_ofs < 0)
1082 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1084 dynamic_string func_name(line);
1085 func_name.substring(1, end_quote_ofs);
1087 line.right(end_quote_ofs + 1).trim();
1088 if (!line.begins_with(","))
1089 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1090 line.right(1).trim();
1092 if (!line.begins_with("["))
1093 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1095 int params_end = find_matching_paren(line, 0, '[', ']');
1097 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1099 dynamic_string params(line);
1100 params.substring(1, params_end);
1102 line.right(params_end + 1).trim();
1104 if ((!line.begins_with(",") && !line.begins_with(")")) || !line.ends_with(")"))
1105 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1107 bool func_has_side_effects = true;
1108 if (line.contains("sideeffects=False"))
1109 func_has_side_effects = false;
1111 apitrace_gl_func_def func_def;
1112 func_def.m_name = func_name;
1113 func_def.m_has_side_effects = func_has_side_effects;
1114 func_def.m_return_type = return_type;
1116 func_def.m_return_gl_type = return_type;
1119 for (a = 0; a < APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE; a++)
1121 if (func_def.m_return_gl_type == g_apitrace_return_type_aliases[a].m_pApitrace_return_type)
1123 func_def.m_return_gl_type = g_apitrace_return_type_aliases[a].m_pSpec_return_type;
1124 func_def.m_return_namespace = g_apitrace_return_type_aliases[a].m_namespace;
1128 if (a == APITRACE_RETURN_TYPE_ALIASES_ARRAY_SIZE)
1130 func_def.m_return_namespace = vogl_find_namespace_from_gl_type(func_def.m_return_gl_type.get_ptr());
1131 if (func_def.m_return_namespace == VOGL_NAMESPACE_INVALID)
1133 // TODO: Here's the list of return/param types that can't be mapped right now - make exception list?
1172 GLbitfield_sync_flush
1174 GLbitfield_client_attrib
1185 //console::warning("%s: Couldn't map namespace %s\n", VOGL_METHOD_NAME, func_def.m_return_gl_type.get_ptr());
1189 #ifdef APITRACE_FUNC_SPECS_DEBUG
1190 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));
1195 bool is_out = false;
1196 bool is_pointer = false;
1197 bool is_const = false;
1198 bool is_opaque = false;
1199 bool is_array = false;
1200 bool is_blob = false;
1201 bool is_index_buffer = false;
1202 bool is_string = false;
1203 bool is_opaque_ctype = false;
1204 dynamic_string array_count_str;
1205 dynamic_string index_count_str;
1206 dynamic_string string_count_str;
1207 dynamic_string index_type_str;
1209 if (params.is_empty())
1212 if (params.begins_with("Out("))
1214 else if (!params.begins_with("("))
1215 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1217 int first_paren = params.find_left("(");
1218 if (first_paren < 0)
1219 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1221 int param_end_ofs = find_matching_paren(params, first_paren);
1222 if (param_end_ofs < 0)
1223 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1225 dynamic_string cur_param;
1227 cur_param.substring(first_paren + 1, param_end_ofs);
1229 params.right(param_end_ofs + 1).trim();
1230 if (params.begins_with(","))
1231 params.right(1).trim();
1233 int right_comma = cur_param.find_right(",");
1234 if (right_comma < 0)
1235 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1237 dynamic_string param_name(cur_param);
1238 param_name.right(right_comma + 1).trim();
1239 cur_param.left(right_comma).trim();
1242 while ((paren_ofs = cur_param.find_left('(')) >= 0)
1244 bool get_count_string = false;
1245 bool count_string_is_optional = false;
1246 dynamic_string *pCount_str = &array_count_str;
1248 if (cur_param.begins_with("Out("))
1250 else if (cur_param.begins_with("Pointer("))
1252 else if (cur_param.begins_with("OpaquePointer("))
1257 else if (cur_param.begins_with("Const("))
1259 else if (cur_param.begins_with("OpaqueBlob("))
1263 get_count_string = true;
1265 else if (cur_param.begins_with("Blob("))
1268 get_count_string = true;
1270 else if (cur_param.begins_with("GLIndexBuffer("))
1272 is_index_buffer = true;
1273 get_count_string = true;
1274 pCount_str = &index_count_str;
1276 else if (cur_param.begins_with("OpaqueArray("))
1280 get_count_string = true;
1282 else if (cur_param.begins_with("Array("))
1285 get_count_string = true;
1287 else if (cur_param.begins_with("String("))
1290 get_count_string = true;
1291 count_string_is_optional = true;
1292 pCount_str = &string_count_str;
1294 else if (cur_param.begins_with("Opaque("))
1296 is_opaque_ctype = true;
1299 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1301 int end_paren_ofs = find_matching_paren(cur_param, paren_ofs);
1302 if (end_paren_ofs < 0)
1303 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1305 cur_param.substring(paren_ofs + 1, end_paren_ofs);
1307 if (get_count_string)
1309 if (cur_param.ends_with("\""))
1311 int start_of_count = cur_param.find_right('\"', cur_param.get_len() - 2);
1312 if (start_of_count < 0)
1313 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1315 if (!pCount_str->is_empty())
1316 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1318 *pCount_str = cur_param;
1319 pCount_str->right(start_of_count).trim();
1321 cur_param.left(start_of_count).trim();
1322 if (!cur_param.ends_with(","))
1323 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1325 cur_param.shorten(1).trim();
1329 int comma_ofs = cur_param.find_right(',');
1330 if ((comma_ofs < 0) && (!count_string_is_optional))
1331 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1335 if (!pCount_str->is_empty())
1336 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1337 *pCount_str = cur_param;
1338 pCount_str->right(comma_ofs + 1).trim();
1340 cur_param.left(comma_ofs).trim();
1345 if (is_index_buffer)
1347 index_type_str = *pCount_str;
1348 *pCount_str = cur_param;
1349 cur_param.truncate(0);
1350 if (index_type_str.contains('(') || index_type_str.contains(','))
1351 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1356 if (is_index_buffer)
1357 cur_param = "GLIndexBuffer";
1359 if (cur_param.is_empty())
1360 return parse_apitrace_gl_param_info_error(param_info_file, line_index);
1362 if (unique_types.find(cur_param) < 0)
1363 unique_types.push_back(cur_param);
1365 if (unique_array_counts.find(array_count_str) < 0)
1366 unique_array_counts.push_back(array_count_str);
1368 apitrace_gl_func_param_def param_def;
1369 param_def.m_name = param_name;
1370 param_def.m_type = cur_param;
1371 param_def.m_array_count_str = array_count_str;
1372 param_def.m_index_count_str = index_count_str;
1373 param_def.m_string_count_str = string_count_str;
1374 param_def.m_index_type_str = index_type_str;
1375 param_def.m_is_out = is_out;
1376 param_def.m_is_pointer = is_pointer;
1377 param_def.m_is_const = is_const;
1378 param_def.m_is_opaque = is_opaque;
1379 param_def.m_is_array = is_array;
1380 param_def.m_is_blob = is_blob;
1381 param_def.m_is_index_buffer = is_index_buffer;
1382 param_def.m_is_string = is_string;
1383 param_def.m_is_opaque_ctype = is_opaque_ctype;
1385 dynamic_string gl_param_type(param_def.m_type);
1387 if (param_def.m_is_opaque_ctype)
1388 gl_param_type.unquote();
1390 param_def.m_namespace = vogl_find_namespace_from_gl_type(gl_param_type.get_ptr());
1391 if (param_def.m_namespace == VOGL_NAMESPACE_INVALID)
1393 //console::warning("%s: Couldn't map namespace %s\n", VOGL_METHOD_NAME, gl_param_type.get_ptr());
1396 for (uint k = 0; k < APITRACE_PARAM_TYPE_ALIASES_ARRAY_SIZE; k++)
1398 if (gl_param_type == g_apitrace_param_type_aliases[k].m_pApitrace_type)
1400 gl_param_type = g_apitrace_param_type_aliases[k].m_pSpec_type;
1405 if ((param_def.m_is_string) || (param_def.m_is_index_buffer))
1406 gl_param_type.append(" *");
1408 if ((param_def.m_is_array) || (param_def.m_is_blob) || (param_def.m_is_pointer))
1410 gl_param_type.append(" *");
1413 param_def.m_gl_type = gl_param_type;
1415 #ifdef APITRACE_FUNC_SPECS_DEBUG
1416 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",
1417 param_name.get_ptr(),
1418 cur_param.get_ptr(),
1419 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));
1420 if (array_count_str.get_len())
1421 printf(" ArrayCountStr: %s\n", array_count_str.get_ptr());
1422 if (index_count_str.get_len())
1423 printf(" IndexCountStr: %s\n", index_count_str.get_ptr());
1424 if (string_count_str.get_len())
1425 printf(" StringCountStr: %s\n", string_count_str.get_ptr());
1426 if (index_type_str.get_len())
1427 printf(" IndexTypeStr: %s\n", index_type_str.get_ptr());
1430 func_def.m_params.push_back(param_def);
1433 m_funcs.push_back(func_def);
1435 #ifdef APITRACE_FUNC_SPECS_DEBUG
1440 #ifdef APITRACE_FUNC_SPECS_DEBUG
1441 printf("Unique types:\n");
1442 unique_types.sort();
1443 for (uint i = 0; i < unique_types.size(); i++)
1444 printf("%s\n", unique_types[i].get_ptr());
1448 printf("Unique array counts:\n");
1449 unique_array_counts.sort();
1450 for (uint i = 0; i < unique_array_counts.size(); i++)
1451 printf("%s\n", unique_array_counts[i].get_ptr());
1458 apitrace_gl_func_def_array m_funcs;
1460 bool parse_apitrace_gl_param_info_error(const dynamic_string_array ¶m_info_file, uint line_index)
1462 console::error("Unrecognized line: %s\n", param_info_file[line_index].get_ptr());
1466 static int find_matching_paren(const dynamic_string &str, uint ofs, uint open_char = '(', uint close_char = ')')
1468 bool in_quoted_string = false;
1469 uint param_count = 0;
1471 while (ofs < str.get_len())
1475 if (in_quoted_string)
1479 in_quoted_string = false;
1484 in_quoted_string = true;
1486 else if (c == open_char)
1488 else if (c == close_char)
1502 //-----------------------------------------------------------------------------------------------------------------------
1504 //-----------------------------------------------------------------------------------------------------------------------
1517 const gl_string_map &get_type_map() const
1521 gl_string_map &get_type_map()
1528 return static_cast<uint>(m_tm.size());
1531 bool is_present(const dynamic_string &type_str) const
1533 return m_tm.find(type_str) != m_tm.end();
1537 const dynamic_string *find(const dynamic_string &type_str) const
1539 gl_string_map::const_iterator it(m_tm.find(type_str));
1540 if (it == m_tm.end())
1545 bool parse_file(const char *pFilename)
1547 cfile_stream tm_file(pFilename, cDataStreamReadable);
1548 if (!tm_file.is_opened())
1550 console::error("Unable to open file \"%s\"!\n", pFilename);
1554 dynamic_string line_str;
1555 while (tm_file.get_remaining())
1557 if (!tm_file.read_line(line_str))
1560 line_str.trim_end();
1562 int comment_ofs = line_str.find_left('#');
1563 if (comment_ofs >= 0)
1565 line_str.truncate(comment_ofs);
1566 line_str.trim_end();
1569 if (line_str.is_empty())
1572 // AccumOp,*,*, GLenum,*,*
1574 dynamic_string_array tokens;
1575 line_str.tokenize(",", tokens);
1576 if (tokens.size() != 6)
1578 console::error("Unexpected number of tokens on line: %s\n", line_str.get_ptr());
1582 for (uint i = 0; i < tokens.size(); i++)
1585 if ((tokens[0].is_empty()) || (tokens[1] != "*") || (tokens[2] != "*") ||
1586 (tokens[3].is_empty()) || (tokens[4] != "*") || (tokens[5] != "*"))
1588 console::error("Unexpected token on line: %s\n", line_str.get_ptr());
1592 if (m_tm.find(tokens[0]) != m_tm.end())
1594 console::error("Duplicate spec type on line: %s\n", line_str.get_ptr());
1598 m_tm.insert(std::make_pair(tokens[0], tokens[3]));
1604 //-----------------------------------------------------------------------------------------------------------------------
1606 void dump_to_file(const char *pFilename) const
1608 FILE *pFile = vogl_fopen(pFilename, "w");
1611 console::info("--- Dumping %u GL types to text file \"%s\"\n", static_cast<uint>(m_tm.size()), pFilename);
1613 for (gl_string_map::const_iterator it = m_tm.begin(); it != m_tm.end(); ++it)
1614 vogl_fprintf(pFile, "\"%s\" = \"%s\"\n", it->first.get_ptr(), it->second.get_ptr());
1620 console::error("Failed writing GL types to file \"%s\"!\n", pFilename);
1628 //-----------------------------------------------------------------------------------------------------------------------
1630 //-----------------------------------------------------------------------------------------------------------------------
1633 dynamic_string m_name;
1634 dynamic_string m_def;
1639 typedef vogl::vector<gl_enum_def> gl_enum_def_vec;
1641 typedef std::map<dynamic_string, gl_enum_def_vec, gl_string_key_comparer> gl_enum_def_vec_map;
1650 bool parse_file(const char *pFilename)
1652 cfile_stream enum_file(pFilename, cDataStreamReadable);
1653 if (!enum_file.is_opened())
1655 console::error("Unable to open file \"%s\"!\n", pFilename);
1659 vogl::vector<gl_enum_def_vec_map::iterator> cur_enums;
1660 bool is_define = false;
1661 bool seen_at_least_one_define = false;
1663 dynamic_string line_str;
1664 while (enum_file.get_remaining())
1666 if (!enum_file.read_line(line_str))
1669 line_str.trim_end();
1671 int comment_ofs = line_str.find_left('#');
1672 if (comment_ofs >= 0)
1674 line_str.truncate(comment_ofs);
1675 line_str.trim_end();
1678 if (line_str.is_empty())
1681 int colon_ofs = line_str.find_left(':');
1683 line_str.left(colon_ofs + 1);
1685 dynamic_string_array tokens;
1686 line_str.tokenize(", \t", tokens);
1688 if ((tokens[0] == "passthru:") || (tokens[0] == "profile:") || (tokens[0].find_left("future_use:") >= 0))
1691 if ((colon_ofs >= 0) && (tokens.size()) &&
1692 ((tokens.back() == "enum:") || (tokens.back() == "define:")))
1694 if (seen_at_least_one_define)
1695 cur_enums.resize(0);
1697 is_define = (tokens.back() == "define:");
1699 for (uint i = 0; i < (tokens.size() - 1); i++)
1701 gl_enum_def_vec_map::iterator cur_enum(m_enums.find(tokens[i]));
1702 if (cur_enum == m_enums.end())
1704 cur_enum = m_enums.insert(std::make_pair(tokens[i], gl_enum_def_vec())).first;
1707 cur_enums.push_back(cur_enum);
1710 else if (tokens.size())
1712 if (line_str.find_left('=') >= 0)
1714 seen_at_least_one_define = true;
1716 if ((tokens.size() != 3) || (tokens[1] != "="))
1718 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1722 if ((tokens[0].is_empty()) || (tokens[1].is_empty()))
1724 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1728 if (!cur_enums.size())
1730 console::error("Enum defined outside of enum block: %s\n", line_str.get_ptr());
1735 def.m_name = tokens[0];
1736 def.m_def = tokens[2];
1737 def.m_alias_flag = false;
1738 def.m_define_flag = is_define;
1740 for (uint i = 0; i < cur_enums.size(); i++)
1741 cur_enums[i]->second.push_back(def);
1743 else if (tokens[0] == "use")
1745 seen_at_least_one_define = true;
1747 if (!cur_enums.size())
1749 console::error("Enum defined outside of enum block: %s\n", line_str.get_ptr());
1754 def.m_name = tokens[2];
1755 def.m_def = tokens[1];
1756 def.m_alias_flag = true;
1757 def.m_define_flag = is_define;
1759 for (uint i = 0; i < cur_enums.size(); i++)
1760 cur_enums[i]->second.push_back(def);
1764 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1770 console::error("Unrecognized line: %s\n", line_str.get_ptr());
1775 for (gl_enum_def_vec_map::iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1777 //printf("%s\n", enum_it->first.get_ptr());
1778 gl_enum_def_vec_map::const_iterator alias_it(m_enums.find(enum_it->first));
1779 VOGL_ASSERT(alias_it != m_enums.end());
1782 uint num_unresolved_aliases;
1786 if (++pass_num == 100)
1788 console::error("Typemap alias depth is too deep, or there are circular aliases\n");
1792 num_unresolved_aliases = 0;
1794 for (gl_enum_def_vec_map::iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1796 gl_enum_def_vec &def_vec = enum_it->second;
1797 for (uint i = 0; i < def_vec.size(); i++)
1799 if (!def_vec[i].m_alias_flag)
1802 gl_enum_def_vec_map::const_iterator alias_it(m_enums.find(def_vec[i].m_def));
1803 if (alias_it == m_enums.end())
1805 console::error("Bad alias enum: %s %s\n", def_vec[i].m_def.get_ptr(), def_vec[i].m_name.get_ptr());
1809 const gl_enum_def_vec &alias_def_vec = alias_it->second;
1812 for (j = 0; j < alias_def_vec.size(); j++)
1814 if (alias_def_vec[j].m_name == def_vec[i].m_name)
1818 if (j == alias_def_vec.size())
1820 console::error("Bad alias enum: %s %s\n", def_vec[i].m_def.get_ptr(), def_vec[i].m_name.get_ptr());
1823 if (alias_def_vec[j].m_alias_flag)
1825 num_unresolved_aliases++;
1829 def_vec[i].m_def = alias_def_vec[j].m_def;
1830 def_vec[i].m_alias_flag = false;
1834 } while (num_unresolved_aliases);
1840 void dump_to_text_file(const char *pFilename) const
1842 FILE *pFile = vogl_fopen(pFilename, "w");
1845 console::info("--- Dumping %u GL enums to file %s\n", static_cast<uint>(m_enums.size()), pFilename);
1847 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1849 vogl_fprintf(pFile, "enum \"%s\"\n", enum_it->first.get_ptr());
1850 for (uint i = 0; i < enum_it->second.size(); i++)
1851 vogl_fprintf(pFile, " \"%s\" = \"%s\"\n", enum_it->second[i].m_name.get_ptr(), enum_it->second[i].m_def.get_ptr());
1858 console::error("Failed writing GL enums to file %s\n", pFilename);
1862 bool dump_to_definition_macro_file(const char *pFilename, const char *pPrefix) const
1864 gl_string_map unique_enums;
1865 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1867 for (uint i = 0; i < enum_it->second.size(); i++)
1868 unique_enums.insert(std::make_pair(enum_it->second[i].m_name, enum_it->second[i].m_def));
1871 console::info("--- Generating \"%s\":\n", pFilename);
1873 FILE *pFile = vogl_fopen(pFilename, "w");
1876 console::error("%s: Failed creating file \"%s\"!\n", VOGL_METHOD_NAME, pFilename);
1880 for (gl_string_map::const_iterator it = unique_enums.begin(); it != unique_enums.end(); ++it)
1881 vogl_fprintf(pFile, "#define %s_%s %s\n", pPrefix, it->first.get_ptr(), it->second.get_ptr());
1887 bool dump_to_description_macro_file(const char *pFilename, const char *pPrefix, const gl_types &gl_typemap, const gl_types &alt_gl_typemap) const
1889 console::info("--- Generating \"%s\":\n", pFilename);
1891 FILE *pFile = vogl_fopen(pFilename, "w");
1894 console::error("%s: Failed creating file \"%s\"!\n", VOGL_METHOD_NAME, pFilename);
1898 for (gl_enum_def_vec_map::const_iterator enum_it = m_enums.begin(); enum_it != m_enums.end(); ++enum_it)
1900 vogl_fprintf(pFile, "DEFINE_GL_ENUM_CATEGORY_BEGIN(%s)\n", enum_it->first.get_ptr());
1902 for (uint i = 0; i < enum_it->second.size(); i++)
1904 const dynamic_string *pGLType = NULL;
1905 pGLType = gl_typemap.find(enum_it->first.get_ptr());
1907 pGLType = alt_gl_typemap.find(enum_it->first.get_ptr());
1909 if (enum_it->second[i].m_define_flag)
1911 vogl_fprintf(pFile, "DEFINE_GL_DEFINE_MEMBER(%s, %s, %s_%s)\n",
1913 enum_it->first.get_ptr(),
1914 pPrefix, enum_it->second[i].m_name.get_ptr());
1918 vogl_fprintf(pFile, "DEFINE_GL_ENUM_MEMBER(%s, %s, \"%s\", \"%s_%s\", %s)\n",
1920 enum_it->first.get_ptr(),
1921 pGLType ? pGLType->get_ptr() : "",
1922 pPrefix, enum_it->second[i].m_name.get_ptr(), enum_it->second[i].m_def.get_ptr());
1926 vogl_fprintf(pFile, "DEFINE_GL_ENUM_CATEGORY_END(%s)\n", enum_it->first.get_ptr());
1935 gl_enum_def_vec_map m_enums;
1938 //-----------------------------------------------------------------------------------------------------------------------
1940 //-----------------------------------------------------------------------------------------------------------------------
1941 #define DEF_FUNCTION_PROTO_PARAM_STR "(a,b,c,d,e,f,g,h)"
1945 apitrace_func_specs m_apitrace_gl_func_specs;
1946 gl_function_specs m_gl_xml_functions;
1947 gl_enums m_gl_enumerations;
1948 gl_enums m_glx_enumerations;
1949 gl_enums m_glx_ext_enumerations;
1951 gl_function_specs m_gl_funcs;
1952 gl_function_specs m_glx_funcs;
1953 gl_function_specs m_glxext_funcs;
1955 gl_function_specs m_all_gl_funcs;
1957 dynamic_string_array m_unique_categories;
1959 gl_string_map m_unique_ctype_enums;
1961 gl_types m_gl_typemap;
1962 gl_types m_glx_typemap;
1964 dynamic_string_array m_gl_so_function_exports;
1966 gl_string_set m_all_gl_ctypes;
1967 gl_string_set m_all_gl_categories;
1968 gl_string_set m_all_array_sizes;
1970 gl_string_map m_pointee_types;
1972 dynamic_string_array m_whitelisted_funcs;
1973 dynamic_string_array m_whitelisted_displaylist_funcs;
1974 dynamic_string_array m_nullable_funcs;
1976 dynamic_string_array m_simple_replay_funcs;
1978 dynamic_string_array funcs_with_custom_array_size_macros;
1979 dynamic_string_array custom_return_param_array_size_macros;
1980 dynamic_string_array funcs_with_return_param_array_size_macros;
1982 gl_string_set custom_array_size_macros;
1983 vogl::vector<uint> custom_array_size_macro_indices;
1984 dynamic_string_array custom_array_size_macro_names;
1989 : m_min_vers(0xFFFF), m_max_vers(0)
1993 dynamic_string m_name;
1997 inline bool operator<(const gl_get &rhs) const
1999 if (m_min_vers < rhs.m_min_vers)
2001 else if (m_min_vers == rhs.m_min_vers)
2003 if (m_max_vers < rhs.m_max_vers)
2005 else if (m_max_vers == rhs.m_max_vers)
2006 return m_name < rhs.m_name;
2012 typedef vogl::hash_map<dynamic_string, gl_get> gl_get_hash_map;
2013 gl_get_hash_map m_gl_gets;
2022 // TODO: I'm going to move the "glspec" dir from under bin to raddebugger/glspec (or whatever)
2023 dynamic_string specdir;
2025 if (g_command_line_params.get_value_as_string(specdir, "specdir"))
2027 file_utils::change_directory(specdir.c_str());
2028 console::warning("Changing current directory to %s\n", specdir.c_str());
2030 else if (!file_utils::does_file_exist("gl.spec"))
2032 if (file_utils::does_file_exist("glspec/gl.spec"))
2034 file_utils::change_directory("glspec");
2035 console::warning("Changing current directory to glspec\n");
2037 else if (file_utils::does_file_exist("../bin/glspec/gl.spec"))
2039 file_utils::change_directory("../bin/glspec");
2040 console::warning("Changing current directory to ../bin/glspec\n");
2044 if (!file_utils::does_file_exist("gl.spec"))
2046 console::error("Can't find find gl.spec, which must be in the current directory!\n");
2050 // -- 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)
2051 if (!m_apitrace_gl_func_specs.parse())
2053 console::error("Failed parsing apitrace param info file!\n");
2057 // -- Load gl.xml, auto-generated from various web pages using several Python scripts
2058 if (!m_gl_xml_functions.parse_gl_xml_file("gl.xml"))
2061 // -- Load the various GL/GLX/GLXEXT enum spec files
2062 m_gl_enumerations.parse_file("enum.spec");
2063 m_glx_enumerations.parse_file("glxenum.spec");
2064 m_glx_ext_enumerations.parse_file("glxenumext.spec");
2066 // -- Load the various GL/GLX/GLXEXT func spec files
2067 bool success = m_gl_funcs.parse_spec_file("gl.spec", cGL);
2070 console::error("Failed parsing gl.spec!\n");
2073 success = m_glx_funcs.parse_spec_file("glx.spec", cGLX);
2076 console::error("Failed parsing glx.spec!\n");
2080 success = m_glxext_funcs.parse_spec_file("glxext.spec", cGLX);
2083 console::error("Failed parsing glxext.spec!\n");
2087 // -- Clean up the GLX func definitions
2088 for (uint i = 0; i < m_glxext_funcs.size(); i++)
2090 int glx_index = m_glx_funcs.find_index(m_glxext_funcs[i].m_name.get_ptr());
2093 console::warning("glxext func %s overriding glx definition\n", m_glxext_funcs[i].m_name.get_ptr());
2094 m_glx_funcs.get_funcs_vec().erase_unordered(glx_index);
2097 int gl_index = m_gl_funcs.find_index(m_glxext_funcs[i].m_name.get_ptr());
2100 console::warning("glxext func %s overriding definition\n", m_glxext_funcs[i].m_name.get_ptr());
2101 m_gl_funcs.get_funcs_vec().erase_unordered(gl_index);
2105 for (uint j = 0; j < m_glxext_funcs.size(); j++)
2107 if (m_glxext_funcs[j].m_name.ends_with("SGIX"))
2109 console::message("deleting glxext func %s\n", m_glxext_funcs[j].m_name.get_ptr());
2111 m_glxext_funcs.get_funcs_vec().erase_unordered(j);
2116 // -- Parse the various spec typemap files
2117 success = m_gl_typemap.parse_file("gl.tm");
2120 console::error("Failed parsing gl.tm!\n");
2124 success = m_glx_typemap.parse_file("glx.tm");
2127 console::error("Failed parsing glx.tm!\n");
2131 // -- Determine the ctypes used by all the GL/GLX functions
2132 if (!determine_ctypes("gl", m_gl_funcs, m_gl_typemap, m_glx_typemap))
2134 console::error("Failed determined gl c types!\n");
2138 if (!determine_ctypes("glX", m_glx_funcs, m_glx_typemap, m_gl_typemap))
2140 console::error("Failed determined glX c types!\n");
2144 if (!determine_ctypes("glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap))
2146 console::error("Failed determined glX c types!\n");
2150 // -- Create master list of all GL/GLX/GLXEXT functions
2151 m_all_gl_funcs = m_gl_funcs;
2152 m_all_gl_funcs += m_glx_funcs;
2153 m_all_gl_funcs += m_glxext_funcs;
2155 // -- Determine the unique list of function API categories
2156 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2158 if (m_unique_categories.find(m_all_gl_funcs[i].m_category) < 0)
2159 m_unique_categories.push_back(m_all_gl_funcs[i].m_category);
2162 m_unique_categories.sort();
2164 // -- Load the GL/GLX function export table, generated by dumping the headers of various drivers
2165 if (!load_gl_so_function_export_list("gl_glx_so_export_list.txt", m_gl_so_function_exports))
2167 console::error("Failed parsing glx.tm!\n");
2171 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);
2172 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);
2173 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);
2175 // -- Create the m_unique_ctype_enums table
2176 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2178 const gl_function_def &func = m_all_gl_funcs[i];
2180 m_unique_ctype_enums.insert(std::make_pair(func.m_return_ctype_enum, func.m_return_ctype));
2181 for (uint p = 0; p < func.m_params.size(); p++)
2182 m_unique_ctype_enums.insert(std::make_pair(func.m_params[p].m_ctype_enum, func.m_params[p].m_ctype));
2185 // -- Create the m_pointee_types table
2188 for (uint i = 0; i < whitelisted_funcs.size(); i++)
2190 int j = simple_replay_funcs.find(whitelisted_funcs[i]);
2192 printf("%s\n", whitelisted_funcs[i].get_ptr());
2197 for (gl_string_map::const_iterator it = m_unique_ctype_enums.begin(); it != m_unique_ctype_enums.end(); ++it)
2199 dynamic_string ctype(it->first.get_ptr());
2200 if (!ctype.ends_with("_PTR"))
2205 if (ctype.ends_with("_CONST"))
2208 if (m_unique_ctype_enums.find(ctype) != m_unique_ctype_enums.end())
2210 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype));
2214 dynamic_string ctype_without_const(ctype);
2215 int ofs = ctype_without_const.find_left("_CONST_");
2218 ctype_without_const.remove(ofs, 6);
2220 if (m_unique_ctype_enums.find(ctype_without_const) != m_unique_ctype_enums.end())
2222 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype_without_const));
2226 dynamic_string ctype_without_const_definition(it->second);
2228 int ptr_ofs = ctype_without_const_definition.find_right('*');
2230 ctype_without_const_definition.remove(ptr_ofs, 1);
2231 int const_ofs = ctype_without_const_definition.find_left("const");
2233 ctype_without_const_definition.remove(const_ofs, 5);
2234 ctype_without_const_definition.trim();
2236 printf("Introducing new ctype from ptr to pointee: %s %s\n", ctype_without_const.get_ptr(), ctype_without_const_definition.get_ptr());
2238 m_unique_ctype_enums.insert(std::make_pair(ctype_without_const, ctype_without_const_definition));
2240 m_pointee_types.insert(std::make_pair(it->first.get_ptr(), ctype_without_const));
2244 // these are NOT actually pointers, they are just big enough to hold pointers (like intptr_t)
2245 //m_pointee_types.insert(std::make_pair("VOGL_GLINTPTR", "VOGL_GLINT"));
2246 //m_pointee_types.insert(std::make_pair("VOGL_GLINTPTRARB", "VOGL_GLINT"));
2247 //m_pointee_types.insert(std::make_pair("VOGL_GLSIZEIPTR", "VOGL_GLSIZEI"));
2249 // -- Read the GL/GLX whitelisted and nullable funcs file
2250 //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);
2251 if (!read_regex_function_array("gl_glx_whitelisted_funcs.txt", m_whitelisted_funcs))
2254 // -- Read the display list whitelist
2255 //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);
2256 if (!read_regex_function_array("gl_glx_displaylist_whitelist.txt", m_whitelisted_displaylist_funcs))
2259 //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);
2260 if (!read_regex_function_array("gl_glx_nullable_funcs.txt", m_nullable_funcs))
2263 if (!read_regex_function_array("gl_glx_simple_replay_funcs.txt", m_simple_replay_funcs))
2266 update_whitelisted_funcs(m_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2268 m_whitelisted_funcs.sort();
2270 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);
2271 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);
2272 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);
2274 uint cur_func_id = 0;
2275 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);
2276 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);
2277 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);
2279 // -- Cross reference the GL spec vs. XML files, for validation
2280 if (!validate_functions(m_gl_xml_functions, m_all_gl_funcs, m_apitrace_gl_func_specs, m_gl_typemap, m_glx_typemap))
2282 console::error("Failed validating functions!\n");
2286 if (!init_gl_gets())
2292 bool func_regex(const char *pPattern) const
2295 if (!r.init(pPattern))
2297 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2302 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2304 if (r.full_match(m_all_gl_funcs[func_index].m_full_name.get_ptr()))
2306 const gl_function_def &func = m_all_gl_funcs[func_index];
2308 printf("%s ", func.m_return_ctype.get_ptr());
2309 printf("%s(", func.m_full_name.get_ptr());
2310 for (uint j = 0; j < func.m_params.size(); j++)
2312 printf("%s %s", func.m_params[j].m_ctype.get_ptr(), func.m_params[j].m_name.get_ptr());
2313 if (j != func.m_params.size() - 1)
2320 printf("Found %u results\n", t);
2325 bool param_regex(const char *pPattern) const
2328 if (!r.init(pPattern))
2330 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2335 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2337 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2339 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2341 if (r.full_match(func_def.m_params[param_index].m_name.get_ptr()))
2343 printf("%s %u %s\n", func_def.m_full_name.get_ptr(), param_index, func_def.m_params[param_index].m_name.get_ptr());
2348 printf("Found %u results\n", t);
2353 bool category_regex(const char *pPattern) const
2356 if (!r.init(pPattern))
2358 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2363 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2365 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2367 if (r.full_match(func_def.m_category.get_ptr()))
2369 printf("%s %s\n", func_def.m_full_name.get_ptr(), func_def.m_category.get_ptr());
2373 printf("Found %u results\n", t);
2378 bool ctype_regex(const char *pPattern) const
2381 if (!r.init(pPattern))
2383 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2388 for (uint func_index = 0; func_index < m_all_gl_funcs.size(); func_index++)
2390 const gl_function_def &func_def = m_all_gl_funcs[func_index];
2392 if (r.full_match(func_def.m_return_ctype.get_ptr()))
2394 printf("%s return %s\n", func_def.m_full_name.get_ptr(), func_def.m_return_ctype.get_ptr());
2398 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2400 if (r.full_match(func_def.m_params[param_index].m_ctype.get_ptr()))
2402 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());
2407 printf("Found %u results\n", t);
2412 bool namespace_regex(const char *pPattern) const
2415 if (!r.init(pPattern))
2417 console::error("Bad regular expression: \"%s\", reason: \"%s\"\n", pPattern, r.get_error().get_ptr());
2422 for (uint func_index = 0; func_index < m_apitrace_gl_func_specs.size(); func_index++)
2424 const apitrace_gl_func_def &func_def = m_apitrace_gl_func_specs[func_index];
2426 if (r.full_match(vogl_get_namespace_name(func_def.m_return_namespace)))
2428 printf("%s return %s\n", func_def.m_name.get_ptr(), vogl_get_namespace_name(func_def.m_return_namespace));
2432 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
2434 const apitrace_gl_func_param_def ¶m = func_def.m_params[param_index];
2436 if (r.full_match(vogl_get_namespace_name(param.m_namespace)))
2438 printf("%s %u %s\n", func_def.m_name.get_ptr(), param_index, vogl_get_namespace_name(param.m_namespace));
2443 printf("Found %u results\n", t);
2448 bool dump_debug_files() const
2450 m_gl_enumerations.dump_to_text_file("dbg_enums.txt");
2451 m_glx_enumerations.dump_to_text_file("dbg_glx_enums.txt");
2452 m_glx_ext_enumerations.dump_to_text_file("dbg_glx_ext_enums.txt");
2454 // -- Dump the definitions for debugging
2455 m_gl_xml_functions.dump_to_file("dbg_gl_xml_funcs.txt");
2456 m_gl_funcs.dump_to_file("dbg_gl_funcs.txt");
2457 m_glx_funcs.dump_to_file("dbg_glx_funcs.txt");
2458 m_glxext_funcs.dump_to_file("dbg_glxext_funcs.txt");
2460 // -- Dump the spec typemap files, for debugging
2461 m_gl_typemap.dump_to_file("dbg_gl_typemap.txt");
2462 m_glx_typemap.dump_to_file("dbg_glx_typemap.txt");
2464 m_all_gl_funcs.dump_to_file("dbg_gl_all_funcs.txt");
2468 // Write a simple macro file line this:
2469 //GL_FUNC(OpenGL,true,GLenum,glGetError,(void),())
2470 //GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a))
2471 pFile = fopen_and_log("dbg_gl_glx_simple_func_macros.txt", "w");
2472 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2474 const gl_function_def &def = m_all_gl_funcs[i];
2475 if (def.m_return == "void")
2476 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());
2478 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());
2482 pFile = fopen_and_log("dbg_gl_glx_types.txt", "w");
2483 for (gl_string_set::const_iterator it = m_all_gl_ctypes.begin(); it != m_all_gl_ctypes.end(); ++it)
2484 vogl_fprintf(pFile, "%s\n", it->get_ptr());
2487 pFile = fopen_and_log("dbg_gl_glx_array_sizes.txt", "w");
2488 for (gl_string_set::const_iterator it = m_all_array_sizes.begin(); it != m_all_array_sizes.end(); ++it)
2489 vogl_fprintf(pFile, "%s\n", it->get_ptr());
2493 printf("--- Functions with custom array size macros:\n");
2494 for (uint i = 0; i < funcs_with_custom_array_size_macros.size(); i++)
2495 printf("%s\n", funcs_with_custom_array_size_macros[i].get_ptr());
2498 printf("--- Whitelisted functions with custom array size macros:\n");
2499 for (uint i = 0; i < funcs_with_custom_array_size_macros.size(); i++)
2501 if (scan_dynamic_string_array_for_string(m_whitelisted_funcs, funcs_with_custom_array_size_macros[i].get_ptr(), true) < 0)
2503 printf("%s\n", funcs_with_custom_array_size_macros[i].get_ptr());
2507 printf("--- All categories:\n");
2508 for (uint i = 0; i < m_unique_categories.size(); i++)
2509 printf("%s\n", m_unique_categories[i].get_ptr());
2512 // -- Write the final whitelist to a file for debugging
2513 file_utils::write_text_file("dbg_final_gl_glx_whitelisted_funcs.txt", m_whitelisted_funcs, true);
2515 VOGL_ASSERT(m_whitelisted_funcs.is_sorted());
2517 for (uint i = 0; i < m_unique_categories.size(); i++)
2519 dynamic_string_array missing_funcs;
2521 bool are_any_whitelisted = false;
2522 for (uint j = 0; j < m_all_gl_funcs.size(); j++)
2524 const gl_function_def &func = m_all_gl_funcs[j];
2525 if (func.m_category != m_unique_categories[i])
2528 bool is_whitelisted = m_whitelisted_funcs.find_sorted(func.m_full_name) >= 0;
2530 if (!is_whitelisted)
2531 missing_funcs.push_back(func.m_full_name);
2533 are_any_whitelisted = true;
2536 if (missing_funcs.size())
2538 printf("--- Non-whitelisted funcs for %s category %s:\n", are_any_whitelisted ? "partially supported" : "unsupported", m_unique_categories[i].get_ptr());
2539 for (uint j = 0; j < missing_funcs.size(); j++)
2540 printf("%s\n", missing_funcs[j].get_ptr());
2545 printf("--- Full support for category: %s\n", m_unique_categories[i].get_ptr());
2552 static FILE *fopen_and_log(const char *pFilename, const char *pMode)
2554 FILE *pFile = vogl_fopen(pFilename, pMode);
2557 console::error("Failed opening file \"%s\" for mode %s\n", pFilename, pMode);
2561 console::info("--- Generating \"%s\":\n", pFilename);
2565 bool generate() const
2567 if (!m_gl_enumerations.dump_to_definition_macro_file("gl_enums.inc", "GL"))
2569 if (!m_glx_enumerations.dump_to_definition_macro_file("glx_enums.inc", "GLX"))
2571 if (!m_glx_ext_enumerations.dump_to_definition_macro_file("glx_ext_enums.inc", "GLX"))
2574 if (!m_gl_enumerations.dump_to_description_macro_file("gl_enum_desc.inc", "GL", m_gl_typemap, m_glx_typemap))
2576 if (!m_glx_enumerations.dump_to_description_macro_file("glx_enum_desc.inc", "GLX", m_glx_typemap, m_gl_typemap))
2578 if (!m_glx_ext_enumerations.dump_to_description_macro_file("glx_ext_desc.inc", "GLX", m_glx_typemap, m_gl_typemap))
2581 // -- Generate the gl_glx_protos.inc include file
2582 FILE *pFile = fopen_and_log("gl_glx_protos.inc", "w");
2585 console::error("Failed creating file gl_glx_protos.inc!\n");
2588 dump_func_proto_macros(pFile, "gl", m_gl_funcs, m_gl_typemap, m_glx_typemap, m_gl_so_function_exports);
2589 dump_func_proto_macros(pFile, "glX", m_glx_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports);
2590 dump_func_proto_macros(pFile, "glX", m_glxext_funcs, m_glx_typemap, m_gl_typemap, m_gl_so_function_exports);
2591 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED\n");
2592 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED_VOID\n");
2593 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL\n");
2594 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL_VOID\n");
2595 vogl_fprintf(pFile, "#undef DEF_PROTO\n");
2596 vogl_fprintf(pFile, "#undef DEF_PROTO_VOID\n");
2599 // -- Generate the gl_glx_ctypes.inc include file
2600 pFile = fopen_and_log("gl_glx_ctypes.inc", "w");
2601 vogl_fprintf(pFile, "DEF_TYPE(VOGL_INVALID_CTYPE, int)\n");
2602 for (gl_string_map::const_iterator it = m_unique_ctype_enums.begin(); it != m_unique_ctype_enums.end(); ++it)
2603 vogl_fprintf(pFile, "DEF_TYPE(%s, %s)\n", it->first.get_ptr(), it->second.get_ptr());
2606 // -- Generate the gl_glx_ctypes_ptr_to_pointee.inc include file
2607 pFile = fopen_and_log("gl_glx_ctypes_ptr_to_pointee.inc", "w");
2608 for (gl_string_map::const_iterator it = m_pointee_types.begin(); it != m_pointee_types.end(); ++it)
2609 vogl_fprintf(pFile, "DEF_PTR_TO_POINTEE_TYPE(%s, %s)\n", it->first.get_ptr(), it->second.get_ptr());
2612 // -- Generate the gl_glx_simple_replay_funcs.inc simple replay funcs file, and update the whitelist
2613 generate_simple_replay_funcs(m_all_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2615 // -- Generate replayer helper macros
2616 generate_replay_func_load_macros(m_all_gl_funcs, m_unique_ctype_enums, m_pointee_types, m_whitelisted_funcs);
2618 // -- Generate the gl_glx_func_defs.inc include file
2619 pFile = fopen_and_log("gl_glx_func_defs.inc", "w");
2622 console::error("Failed creating file gl_glx_func_defs.inc!\n");
2625 dump_inc_file_header(pFile);
2626 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);
2627 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);
2628 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);
2629 dump_function_def_undef_macros(pFile);
2632 // -- Generate the gl_glx_func_return_param_array_size_macros.inc include file
2633 pFile = fopen_and_log("gl_glx_func_return_param_array_size_macros.inc", "w");
2636 console::error("Failed creating file gl_glx_func_return_param_array_size_macros.inc!\n");
2639 for (uint i = 0; i < custom_return_param_array_size_macros.size(); i++)
2641 dynamic_string macro_name(custom_return_param_array_size_macros[i]);
2642 int n = macro_name.find_left('(');
2644 macro_name.truncate(n);
2646 int num_params = custom_return_param_array_size_macros[i].count_char(',') + 1;
2648 dynamic_string params("(");
2649 for (int j = 0; j < num_params; j++)
2652 params.append_char(',');
2653 params.append_char((char)('a' + j));
2657 vogl_fprintf(pFile, "#ifndef %s\n", macro_name.get_ptr());
2658 vogl_fprintf(pFile, " #define %s%s -1\n", macro_name.get_ptr(), params.get_ptr());
2659 vogl_fprintf(pFile, "#endif\n");
2663 // -- Generate the gl_glx_func_descs.inc include file
2664 pFile = fopen_and_log("gl_glx_func_descs.inc", "w");
2665 dump_inc_file_header(pFile);
2666 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);
2667 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);
2668 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);
2669 dump_function_def_undef_macros(pFile);
2672 pFile = fopen_and_log("gl_glx_categories.inc", "w");
2673 for (gl_string_set::const_iterator it = m_all_gl_categories.begin(); it != m_all_gl_categories.end(); ++it)
2674 vogl_fprintf(pFile, "DEF_CATEGORY(%s)\n", it->get_ptr());
2677 // -- Generate the gl_glx_array_size_macros.inc include file
2678 pFile = fopen_and_log("gl_glx_array_size_macros.inc", "w");
2679 for (gl_string_set::const_iterator it = custom_array_size_macros.begin(); it != custom_array_size_macros.end(); ++it)
2681 dynamic_string macro_name(it->get_ptr());
2682 macro_name.truncate(macro_name.find_left('('));
2683 vogl_fprintf(pFile, "#ifndef %s\n", macro_name.get_ptr());
2684 vogl_fprintf(pFile, " #define %s%s -1\n", macro_name.get_ptr(), DEF_FUNCTION_PROTO_PARAM_STR);
2685 vogl_fprintf(pFile, "#endif\n");
2689 // -- Generate the gl_glx_array_size_macros_validator.inc include file
2690 pFile = fopen_and_log("gl_glx_array_size_macros_validator.inc", "w");
2691 for (uint i = 0; i < custom_array_size_macro_indices.size(); i++)
2693 uint j = custom_array_size_macro_indices[i];
2694 uint func_index = j >> 16;
2695 uint param_index = j & 0xFFFF;
2696 VOGL_NOTE_UNUSED(param_index);
2698 const dynamic_string ¯o_name = custom_array_size_macro_names[i];
2700 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());
2701 vogl_fprintf(pFile, " #ifdef %s\n", macro_name.get_ptr());
2702 vogl_fprintf(pFile, " VALIDATE_ARRAY_SIZE_MACRO_DEFINED(%s, 0x%08X)\n", macro_name.get_ptr(), custom_array_size_macro_indices[i]);
2703 vogl_fprintf(pFile, " #else\n");
2704 vogl_fprintf(pFile, " VALIDATE_ARRAY_SIZE_MACRO_NOT_DEFINED(%s, 0x%08X)\n", macro_name.get_ptr(), custom_array_size_macro_indices[i]);
2705 vogl_fprintf(pFile, " #endif\n");
2706 vogl_fprintf(pFile, "#endif\n");
2710 // -- Generate the gl_glx_custom_return_param_array_size_macro_validator.inc include file
2711 pFile = fopen_and_log("gl_glx_custom_return_param_array_size_macro_validator.inc", "w");
2712 for (uint i = 0; i < custom_return_param_array_size_macros.size(); i++)
2714 dynamic_string macro_name(custom_return_param_array_size_macros[i]);
2715 int n = macro_name.find_left('(');
2717 macro_name.truncate(n);
2719 vogl_fprintf(pFile, "#ifdef %s\n", macro_name.get_ptr());
2720 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());
2721 vogl_fprintf(pFile, "#else\n");
2722 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());
2723 vogl_fprintf(pFile, "#endif\n");
2727 // -- Generate the gl_glx_custom_func_handler_validator.inc include file
2728 pFile = fopen_and_log("gl_glx_custom_func_handler_validator.inc", "w");
2729 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
2731 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());
2732 vogl_fprintf(pFile, " CUSTOM_FUNC_HANDLER_DEFINED(%u)\n", i);
2733 vogl_fprintf(pFile, "#else\n");
2734 vogl_fprintf(pFile, " CUSTOM_FUNC_HANDLER_NOT_DEFINED(%u)\n", i);
2735 vogl_fprintf(pFile, "#endif\n");
2739 // -- Generate the gl_glx_array_size_macro_func_param_indices.inc include file
2740 pFile = fopen_and_log("gl_glx_array_size_macro_func_param_indices.inc", "w");
2741 for (uint i = 0; i < custom_array_size_macro_indices.size(); i++)
2744 vogl_fprintf(pFile, ",");
2745 vogl_fprintf(pFile, "0x%08X", custom_array_size_macro_indices[i]);
2747 vogl_fprintf(pFile, "\n");
2749 vogl_fprintf(pFile, "\n");
2752 if (!generate_gl_gets_inc_file())
2755 if (!generate_libvogltrace_export_script())
2762 //-----------------------------------------------------------------------------------------------------------------------
2764 //-----------------------------------------------------------------------------------------------------------------------
2767 static const struct gl_get_files
2769 const char *m_pFilename;
2771 } s_gl_get_files[] =
2773 { "gl10_gets.txt", 0x10 },
2774 { "gl15_gets.txt", 0x15 },
2775 { "gl21_gets.txt", 0x21 },
2776 { "gl33_gets.txt", 0x33 },
2777 { "gl40_gets.txt", 0x40 },
2778 { "gl41_gets.txt", 0x41 },
2779 { "gl42_gets.txt", 0x42 },
2780 { "gl43_gets.txt", 0x43 }
2783 for (uint file_iter = 0; file_iter < sizeof(s_gl_get_files) / sizeof(s_gl_get_files[0]); file_iter++)
2785 const char *pFilename = s_gl_get_files[file_iter].m_pFilename;
2787 // typedef vogl::hash_map<dynamic_string, gl_get> gl_get_hash_map;
2788 // gl_get_hash_map m_gl_gets;
2790 dynamic_string_array get_names;
2792 if (!file_utils::read_text_file(pFilename, get_names, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
2795 for (uint i = 0; i < get_names.size(); i++)
2797 if ((get_names[i].toupper().compare(get_names[i], true) != 0) || (get_names[i].contains(' ')))
2799 console::error("In file %s, enum name is invalid: \"%s\"\n", pFilename, get_names[i].get_ptr());
2803 gl_get_hash_map::insert_result ins_res(m_gl_gets.insert(get_names[i], gl_get()));
2804 gl_get &gl_get_obj = ins_res.first->second;
2805 gl_get_obj.m_name = get_names[i];
2806 gl_get_obj.m_min_vers = vogl::math::minimum(gl_get_obj.m_min_vers, s_gl_get_files[file_iter].m_vers);
2807 gl_get_obj.m_max_vers = vogl::math::maximum(gl_get_obj.m_max_vers, s_gl_get_files[file_iter].m_vers);
2811 //for (gl_get_hash_map::const_iterator it = m_gl_gets.begin(); it != m_gl_gets.end(); ++it)
2812 // printf("%s 0x%04X 0x%04X\n", it->first.get_ptr(), it->second.m_min_vers, it->second.m_max_vers);
2817 bool generate_libvogltrace_export_script() const
2820 // We're writing an anonymous version map on purpose, otherwise bad shit happens in some apps!
2830 const char *pFilename = "libvogltrace_linker_script.txt";
2831 cfile_stream export_script(pFilename, cDataStreamWritable);
2833 console::info("--- Generating \"%s\":\n", pFilename);
2835 export_script.puts("{\n");
2836 export_script.puts(" global:\n");
2838 for (uint i = 0; i < m_gl_so_function_exports.size(); i++)
2839 export_script.printf(" %s;\n", m_gl_so_function_exports[i].get_ptr());
2841 dynamic_string_array nongenerated_exports;
2842 file_utils::read_text_file("gl_glx_nongenerated_so_export_list.txt", nongenerated_exports, file_utils::cRTFPrintWarningMessages);
2844 for (uint i = 0; i < nongenerated_exports.size(); i++)
2845 export_script.printf(" %s;\n", nongenerated_exports[i].get_ptr());
2847 export_script.puts(" local:\n");
2848 export_script.puts(" *;\n");
2849 export_script.puts("};\n");
2854 //-----------------------------------------------------------------------------------------------------------------------
2855 // generate_gl_gets_inc_file
2856 //-----------------------------------------------------------------------------------------------------------------------
2857 bool generate_gl_gets_inc_file() const
2859 // Note: I used this to generate our first gl_gets.inc file, which then had to be hand edited.
2860 const char *pFilename = "gl_gets_approx.inc";
2861 cfile_stream gl_gets_inc(pFilename, cDataStreamWritable);
2863 if (!gl_gets_inc.is_opened())
2865 console::error("Failed creating file %s!\n", pFilename);
2869 console::info("--- Generating \"%s\":\n", pFilename);
2871 vogl::vector<gl_get> sorted_gets;
2872 for (gl_get_hash_map::const_iterator it = m_gl_gets.begin(); it != m_gl_gets.end(); ++it)
2873 sorted_gets.push_back(it->second);
2876 int prev_min_vers = -1;
2877 int prev_max_vers = -1;
2878 for (uint i = 0; i < sorted_gets.size(); i++)
2880 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)))
2882 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);
2883 prev_min_vers = sorted_gets[i].m_min_vers;
2884 prev_max_vers = sorted_gets[i].m_max_vers;
2886 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);
2892 //-----------------------------------------------------------------------------------------------------------------------
2893 // ensure_gl_exports_are_defined
2894 //-----------------------------------------------------------------------------------------------------------------------
2895 bool ensure_gl_exports_are_defined(gl_function_specs &gl_funcs, const gl_function_specs &glx_funcs, const gl_function_specs &glxext_funcs)
2897 cfile_stream list_file("gl_glx_so_export_list.txt", cDataStreamReadable);
2898 if (!list_file.is_opened())
2901 dynamic_string line_str;
2902 while (list_file.get_remaining())
2904 if (!list_file.read_line(line_str))
2908 if (line_str.is_empty())
2911 dynamic_string func;
2912 const gl_function_specs *pSpecs = NULL;
2913 if (line_str.find_left("glX") == 0)
2915 func.set(line_str).right(3);
2916 pSpecs = &glx_funcs;
2918 else if (line_str.find_left("gl") == 0)
2920 func.set(line_str).right(2);
2926 console::warning("Unrecognized SO export: %s\n", line_str.get_ptr());
2930 const gl_function_def *pFunc = pSpecs->find(func.get_ptr());
2931 if ((!pFunc) && (pSpecs == &glx_funcs))
2933 pSpecs = &glxext_funcs;
2934 pFunc = pSpecs->find(func.get_ptr());
2939 if (func.ends_with("OES", true) || func.ends_with("x", true) || func.ends_with("NV", true) || func.ends_with("NVX") ||
2940 func.ends_with("SGI") || func.ends_with("EXT") || func.ends_with("X") || func.ends_with("xv") || func.ends_with("Autodesk") ||
2941 func.ends_with("WIN"))
2943 //console::warning("Skipping missing SO export: %s\n", line_str.get_ptr());
2947 console::warning("Can't find SO export in spec files: %s\n", line_str.get_ptr());
2951 //printf("Found %s\n", pFunc->m_name.get_ptr());
2957 //-----------------------------------------------------------------------------------------------------------------------
2958 // load_gl_so_function_export_list
2959 //-----------------------------------------------------------------------------------------------------------------------
2960 bool load_gl_so_function_export_list(const char *pFilename, dynamic_string_array &gl_so_function_exports)
2962 cfile_stream list_file(pFilename, cDataStreamReadable);
2963 if (!list_file.is_opened())
2966 dynamic_string line_str;
2967 while (list_file.get_remaining())
2969 if (!list_file.read_line(line_str))
2973 if (line_str.is_empty())
2976 gl_so_function_exports.push_back(line_str);
2979 gl_so_function_exports.sort();
2984 //-----------------------------------------------------------------------------------------------------------------------
2985 // translate_ctype_to_ctype_enum
2986 //-----------------------------------------------------------------------------------------------------------------------
2987 dynamic_string translate_ctype_to_ctype_enum(dynamic_string ctype)
2989 ctype.trim().toupper().replace("_", "");
2994 ctype.replace(" *", "*", true, &num_found);
2995 } while (num_found);
2999 ctype.replace(" ", " ", true, &num_found);
3000 } while (num_found);
3002 ctype.replace(" ", "_");
3003 ctype.replace("*", "_PTR");
3005 return "VOGL_" + ctype;
3008 //-----------------------------------------------------------------------------------------------------------------------
3010 //-----------------------------------------------------------------------------------------------------------------------
3011 bool determine_ctypes(const char *pFunc_prefix, gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap)
3013 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3015 gl_function_def &func = gl_funcs[func_index];
3017 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3019 if (func.m_return == "void")
3020 func.m_return_ctype = "void";
3023 const dynamic_string *pCType = typemap.find(func.m_return);
3025 pCType = alt_typemap.find(func.m_return);
3028 console::warning("Unable to map spec type %s\n", func.m_return.get_ptr());
3032 func.m_return_ctype = *pCType;
3034 func.m_return_ctype_enum = translate_ctype_to_ctype_enum(func.m_return_ctype);
3036 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3038 gl_function_param ¶m = func.m_params[param_index];
3040 const dynamic_string *pCType = typemap.find(param.m_type);
3042 pCType = alt_typemap.find(param.m_type);
3045 console::warning("Unable to map spec type %s\n", param.m_type.get_ptr());
3049 dynamic_string type_prefix;
3051 dynamic_string type_suffix("");
3052 if ((param.m_semantic == "array") || (param.m_semantic == "reference"))
3056 if (param.m_direction == "in")
3058 if (!pCType->ends_with("const"))
3059 type_prefix = "const ";
3063 dynamic_string full_ctype(cVarArg, "%s%s%s", type_prefix.get_ptr(), pCType->get_ptr(), type_suffix.get_ptr());
3065 param.m_ctype = full_ctype;
3066 param.m_ctype_enum = translate_ctype_to_ctype_enum(full_ctype);
3073 //-----------------------------------------------------------------------------------------------------------------------
3074 // get_func_proto_macro
3075 //-----------------------------------------------------------------------------------------------------------------------
3076 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
3078 dynamic_string proto;
3080 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3082 dynamic_string exported_param((func.m_return == "void") ? "DEF_PROTO_INTERNAL_VOID" : "DEF_PROTO_INTERNAL");
3083 int export_index = sorted_gl_so_function_exports.find_sorted(full_func_name);
3084 if (export_index >= 0)
3085 exported_param = (func.m_return == "void") ? "DEF_PROTO_EXPORTED_VOID" : "DEF_PROTO_EXPORTED";
3087 dynamic_string category(func.m_category.get_len() ? func.m_category.get_ptr() : "UNDEFINED");
3089 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());
3091 proto.format_append("%s, ", full_func_name.get_ptr());
3093 proto.format_append("(");
3094 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3096 const gl_function_param ¶m = func.m_params[param_index];
3098 proto.format_append("%s%s%s", param.m_ctype.get_ptr(), param.m_ctype.ends_with("*") ? "" : " ", param.m_name.get_ptr());
3099 if (param_index != func.m_params.size() - 1)
3100 proto.format_append(", ");
3103 proto.format_append("), ");
3105 proto.format_append("(");
3106 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3108 proto.format_append("%s", func.m_params[param_index].m_name.get_ptr());
3109 if (param_index != func.m_params.size() - 1)
3110 proto.format_append(", ");
3113 proto.format_append(") )");
3118 //-----------------------------------------------------------------------------------------------------------------------
3119 // process_func_protos
3120 //-----------------------------------------------------------------------------------------------------------------------
3121 bool process_func_protos(
3122 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,
3123 gl_string_set &all_gl_ctypes, gl_string_set &all_gl_categories, gl_string_set &array_sizes)
3125 VOGL_NOTE_UNUSED(pFunc_prefix);
3126 VOGL_NOTE_UNUSED(typemap);
3127 VOGL_NOTE_UNUSED(alt_typemap);
3128 VOGL_NOTE_UNUSED(sorted_gl_so_function_exports);
3130 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3132 const gl_function_def &func = gl_funcs[func_index];
3134 all_gl_categories.insert(func.m_category);
3135 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3137 const gl_function_param ¶m = func.m_params[param_index];
3139 all_gl_ctypes.insert(param.m_ctype);
3140 array_sizes.insert(param.m_array_size);
3147 //-----------------------------------------------------------------------------------------------------------------------
3148 // dump_func_proto_macros
3149 //-----------------------------------------------------------------------------------------------------------------------
3150 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
3152 VOGL_NOTE_UNUSED(typemap);
3153 VOGL_NOTE_UNUSED(alt_typemap);
3155 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3157 const gl_function_def &func = gl_funcs[func_index];
3159 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3161 vogl_fprintf(pFile, "%s%s\n", (func.m_return_ctype == "void") ? "DEF_PROTO_VOID" : "DEF_PROTO", func_proto.get_ptr());
3167 //-----------------------------------------------------------------------------------------------------------------------
3168 // func_param_translate_array_size
3169 //-----------------------------------------------------------------------------------------------------------------------
3170 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
3172 if (pCustom_macro_flag)
3173 *pCustom_macro_flag = false;
3175 if (param.m_array_size.begins_with("[") && param.m_array_size.ends_with("]"))
3177 dynamic_string array_size_param(param.m_array_size);
3178 array_size_param.mid(1, array_size_param.get_len() - 2);
3180 for (uint i = 0; i < func.m_params.size(); i++)
3181 if ((func.m_params[i].m_name == array_size_param) ||
3182 ((func.m_params[i].m_name + "*1") == array_size_param) ||
3183 ((func.m_params[i].m_name + "*2") == array_size_param) ||
3184 ((func.m_params[i].m_name + "*3") == array_size_param) ||
3185 ((func.m_params[i].m_name + "*4") == array_size_param) ||
3186 ((func.m_params[i].m_name + "*5") == array_size_param) ||
3187 ((func.m_params[i].m_name + "*6") == array_size_param) ||
3188 ((func.m_params[i].m_name + "*7") == array_size_param) ||
3189 ((func.m_params[i].m_name + "*8") == array_size_param) ||
3190 ((func.m_params[i].m_name + "*9") == array_size_param) ||
3191 ((func.m_params[i].m_name + "*10") == array_size_param) ||
3192 ((func.m_params[i].m_name + "*11") == array_size_param) ||
3193 ((func.m_params[i].m_name + "*12") == array_size_param) ||
3194 ((func.m_params[i].m_name + "*13") == array_size_param) ||
3195 ((func.m_params[i].m_name + "*14") == array_size_param) ||
3196 ((func.m_params[i].m_name + "*15") == array_size_param) ||
3197 ((func.m_params[i].m_name + "*16") == array_size_param))
3199 if (func.m_params[i].m_semantic == "value")
3200 return array_size_param;
3201 //else if (func.m_params[i].m_semantic == "reference")
3202 // return dynamic_string(cVarArg, "%s ? *%s : -2", array_size_param.get_ptr(), array_size_param.get_ptr());
3203 //else if ((func.m_params[i].m_semantic == "array") && (func.m_params[i].m_array_size == "[1]"))
3204 // return dynamic_string(cVarArg, "%s ? *%s : -2", array_size_param.get_ptr(), array_size_param.get_ptr());
3207 if (array_size_param == "0" || array_size_param == "1" || array_size_param == "2" ||
3208 array_size_param == "3" || array_size_param == "4" || array_size_param == "5" ||
3209 array_size_param == "6" || array_size_param == "7" || array_size_param == "8" ||
3210 array_size_param == "9" || array_size_param == "12" || array_size_param == "16")
3212 return array_size_param;
3215 if (array_size_param.begins_with("COMPSIZE(") && array_size_param.ends_with(")"))
3217 dynamic_string comp_size_param(array_size_param);
3218 comp_size_param.mid(9, comp_size_param.get_len() - 10);
3220 // each of these are assumed to be a GL enum
3221 if ((comp_size_param == "pname") || (comp_size_param == "attribute") ||
3222 (comp_size_param == "id") || //(comp_size_param == "buffer") ||
3223 (comp_size_param == "map") || //(comp_size_param == "name") ||
3224 (comp_size_param == "path") || (comp_size_param == "query") ||
3225 (comp_size_param == "target") || (comp_size_param == "type") ||
3226 (comp_size_param == "value"))
3227 return dynamic_string(cVarArg, "DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM(%s)", comp_size_param.get_ptr());
3229 // these might be wrong
3230 for (uint i = 0; i < func.m_params.size(); i++)
3231 if (((func.m_params[i].m_name + "*2") == comp_size_param) ||
3232 ((func.m_params[i].m_name + "*3") == comp_size_param) ||
3233 ((func.m_params[i].m_name + "*4") == comp_size_param))
3235 return dynamic_string(cVarArg, "DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM(%s)", comp_size_param.get_ptr());
3240 if (pCustom_macro_flag)
3241 *pCustom_macro_flag = true;
3243 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());
3244 return custom_array_size;
3247 //-----------------------------------------------------------------------------------------------------------------------
3248 // create_array_size_macros
3249 // TODO: use funcs_with_custom_array_size_macros[] vs. scanning for DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_FUNC_
3250 //-----------------------------------------------------------------------------------------------------------------------
3251 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,
3252 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
3254 VOGL_NOTE_UNUSED(typemap);
3255 VOGL_NOTE_UNUSED(alt_typemap);
3257 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3259 const gl_function_def &func = gl_funcs[func_index];
3261 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3263 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3265 const gl_function_param ¶m = func.m_params[param_index];
3267 if (param.m_semantic == "array")
3269 dynamic_string array_size_macro(func_param_translate_array_size(pFunc_prefix, func, param, func_proto));
3270 if (array_size_macro.begins_with("DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_FUNC_"))
3272 custom_array_size_macros.insert(array_size_macro);
3274 // oh god this is ugly
3275 dynamic_string macro_name(array_size_macro);
3276 int n = macro_name.find_left('(');
3278 macro_name.truncate(n);
3280 custom_array_size_macro_indices.push_back((cur_func_id << 16) | param_index);
3281 custom_array_size_macro_names.push_back(macro_name);
3290 //-----------------------------------------------------------------------------------------------------------------------
3291 // process_func_defs
3292 //-----------------------------------------------------------------------------------------------------------------------
3293 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,
3294 const dynamic_string_array &whitelisted_funcs,
3295 const dynamic_string_array &nullable_funcs,
3296 dynamic_string_array &funcs_with_custom_array_size_macros,
3297 dynamic_string_array &custom_return_param_array_size_macros,
3298 dynamic_string_array &funcs_with_return_param_array_size_macros)
3300 VOGL_NOTE_UNUSED(typemap);
3301 VOGL_NOTE_UNUSED(alt_typemap);
3302 VOGL_NOTE_UNUSED(nullable_funcs);
3304 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3306 const gl_function_def &func = gl_funcs[func_index];
3308 dynamic_string full_func_name(func.m_full_name); //cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3310 bool is_in_whitelist = false;
3311 VOGL_NOTE_UNUSED(is_in_whitelist);
3312 for (uint i = 0; i < whitelisted_funcs.size(); i++)
3314 if (whitelisted_funcs[i] == full_func_name)
3316 is_in_whitelist = true;
3321 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3323 // TODO: This (func_has_custom_array_size_macros) is dead code
3324 bool func_has_custom_array_size_macros = false;
3326 dynamic_string func_params;
3328 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3330 const gl_function_param ¶m = func.m_params[param_index];
3332 func_params.append(param.m_name);
3333 if (param_index != (func.m_params.size() - 1))
3334 func_params.append(", ");
3337 if (func.m_return != "void")
3339 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());
3341 custom_return_param_array_size_macros.push_back(return_param_compute_array_size_macro_name);
3342 funcs_with_return_param_array_size_macros.push_back(full_func_name);
3345 if (func_has_custom_array_size_macros)
3347 funcs_with_custom_array_size_macros.push_back(full_func_name);
3354 //-----------------------------------------------------------------------------------------------------------------------
3355 // dump_func_def_macros
3356 //-----------------------------------------------------------------------------------------------------------------------
3357 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,
3358 const dynamic_string_array &whitelisted_funcs,
3359 const dynamic_string_array &nullable_funcs) const
3361 VOGL_NOTE_UNUSED(typemap);
3362 VOGL_NOTE_UNUSED(alt_typemap);
3363 VOGL_NOTE_UNUSED(nullable_funcs);
3365 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3367 const gl_function_def &func = gl_funcs[func_index];
3369 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3371 bool is_in_whitelist = false;
3372 VOGL_NOTE_UNUSED(is_in_whitelist);
3373 for (uint i = 0; i < whitelisted_funcs.size(); i++)
3375 if (whitelisted_funcs[i] == full_func_name)
3377 is_in_whitelist = true;
3382 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3384 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());
3386 vogl_fprintf(pFile, "#ifdef DEF_FUNCTION_CUSTOM_HANDLER_%s\n", full_func_name.get_ptr());
3388 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_HANDLER_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3389 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_HANDLER_%s\n", full_func_name.get_ptr());
3391 vogl_fprintf(pFile, "#else\n");
3393 vogl_fprintf(pFile, " DEF_FUNCTION_BEGIN%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3395 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s\n", full_func_name.get_ptr());
3396 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3397 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_FUNC_PROLOG_%s\n", full_func_name.get_ptr());
3398 vogl_fprintf(pFile, " #endif\n");
3400 vogl_fprintf(pFile, " DEF_FUNCTION_INIT%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3402 bool func_has_custom_array_size_macros = false;
3404 dynamic_string func_params;
3406 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3408 const gl_function_param ¶m = func.m_params[param_index];
3410 func_params.append(param.m_name);
3411 if (param_index != (func.m_params.size() - 1))
3412 func_params.append(", ");
3414 if (param.m_direction != "in")
3417 if (param.m_semantic == "value")
3419 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());
3421 else if (param.m_semantic == "array")
3423 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3424 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());
3426 else if (param.m_semantic == "reference")
3428 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());
3432 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_CALLER_%s\n", full_func_name.get_ptr());
3433 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_CALLER_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3434 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_CALLER_%s\n", full_func_name.get_ptr());
3436 vogl_fprintf(pFile, " #else\n");
3438 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_PROLOG_%s\n", full_func_name.get_ptr());
3439 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_PROLOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3440 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_PROLOG_%s\n", full_func_name.get_ptr());
3441 vogl_fprintf(pFile, " #endif\n");
3443 vogl_fprintf(pFile, " DEF_FUNCTION_CALL_GL%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3445 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_GL_EPILOG_%s\n", full_func_name.get_ptr());
3446 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_GL_EPILOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3447 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_GL_EPILOG_%s\n", full_func_name.get_ptr());
3448 vogl_fprintf(pFile, " #endif\n");
3450 vogl_fprintf(pFile, " #endif\n");
3452 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3454 const gl_function_param ¶m = func.m_params[param_index];
3455 if (param.m_direction != "out")
3458 if (param.m_semantic == "value")
3460 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());
3462 else if (param.m_semantic == "array")
3464 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3465 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());
3467 else if (param.m_semantic == "reference")
3469 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());
3473 vogl_fprintf(pFile, " #ifdef DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s\n", full_func_name.get_ptr());
3474 vogl_fprintf(pFile, " DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s%s\n", full_func_name.get_ptr(), func_proto.get_ptr());
3475 vogl_fprintf(pFile, " #undef DEF_FUNCTION_CUSTOM_FUNC_EPILOG_%s\n", full_func_name.get_ptr());
3476 vogl_fprintf(pFile, " #endif\n");
3478 if (func.m_return != "void")
3480 //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());
3481 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());
3483 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());
3486 vogl_fprintf(pFile, " DEF_FUNCTION_END%s%s\n", func.m_return == "void" ? "_VOID" : "", func_proto.get_ptr());
3488 vogl_fprintf(pFile, "#endif\n");
3489 vogl_fprintf(pFile, "\n");
3495 //-----------------------------------------------------------------------------------------------------------------------
3496 // dump_func_desc_macros
3497 //-----------------------------------------------------------------------------------------------------------------------
3498 bool dump_func_desc_macros(
3499 FILE *pFile, const char *pFunc_prefix,
3500 const gl_function_specs &gl_funcs, const gl_types &typemap, const gl_types &alt_typemap, const apitrace_func_specs &apitrace_gl_func_specs,
3501 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
3503 VOGL_NOTE_UNUSED(typemap);
3504 VOGL_NOTE_UNUSED(alt_typemap);
3506 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3508 const gl_function_def &func = gl_funcs[func_index];
3510 dynamic_string full_func_name(cVarArg, "%s%s", pFunc_prefix, func.m_name.get_ptr());
3511 VOGL_ASSERT(full_func_name.compare(func.m_full_name, true) == 0);
3513 const apitrace_gl_func_def *pApitrace_func_def = apitrace_gl_func_specs.find(full_func_name.get_ptr());
3515 bool is_in_whitelist = whitelisted_funcs.find(full_func_name) != cInvalidIndex;
3516 bool is_nullable = nullable_funcs.find(full_func_name) != cInvalidIndex;
3518 bool is_whitelisted_for_displaylists = false;
3519 for (uint i = 0; i < whitelisted_displaylists_funcs.size(); i++)
3521 if (regexp_full_match(func.m_full_name.get_ptr(), whitelisted_displaylists_funcs[i].get_ptr()))
3523 is_whitelisted_for_displaylists = true;
3528 if (is_whitelisted_for_displaylists)
3530 if (func.m_notlistable)
3532 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());
3536 dynamic_string func_proto(get_func_proto_macro(pFunc_prefix, func, sorted_gl_so_function_exports));
3538 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());
3540 vogl_fprintf(pFile, "DEF_FUNCTION_BEGIN%s\n", func_proto.get_ptr());
3542 vogl_namespace_t return_namespace = VOGL_NAMESPACE_UNKNOWN;
3543 if (pApitrace_func_def)
3544 return_namespace = pApitrace_func_def->m_return_namespace;
3546 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(),
3547 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");
3549 if (func.m_params.size())
3551 vogl_fprintf(pFile, " DEF_FUNCTION_BEGIN_PARAMS\n");
3552 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3554 const gl_function_param ¶m = func.m_params[param_index];
3556 vogl_namespace_t param_namespace = VOGL_NAMESPACE_UNKNOWN;
3557 if (pApitrace_func_def)
3559 VOGL_ASSERT(param_index < pApitrace_func_def->m_params.size());
3560 if (param_index < pApitrace_func_def->m_params.size())
3561 param_namespace = pApitrace_func_def->m_params[param_index].m_namespace;
3564 dynamic_string dir(param.m_direction);
3567 if (param.m_semantic == "value")
3569 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());
3571 else if (param.m_semantic == "array")
3573 vogl_fprintf(pFile, " // %s ArraySize=%s\n", param.m_name.get_ptr(), param.m_array_size.get_ptr());
3574 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());
3576 else if (param.m_semantic == "reference")
3578 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());
3581 vogl_fprintf(pFile, " DEF_FUNCTION_END_PARAMS\n");
3584 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());
3586 vogl_fprintf(pFile, "DEF_FUNCTION_END%s\n", func_proto.get_ptr());
3588 vogl_fprintf(pFile, "\n");
3594 //-----------------------------------------------------------------------------------------------------------------------
3595 // dump_inc_file_header
3596 //-----------------------------------------------------------------------------------------------------------------------
3597 void dump_inc_file_header(FILE *pFile) const
3599 vogl_fprintf(pFile, "// Auto-generated by voglgen. Don't hand modify!\n\n");
3602 //-----------------------------------------------------------------------------------------------------------------------
3603 // dump_function_def_undef_macros
3604 //-----------------------------------------------------------------------------------------------------------------------
3605 void dump_function_def_undef_macros(FILE *pFile) const
3607 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED\n");
3608 vogl_fprintf(pFile, "#undef DEF_PROTO_EXPORTED_VOID\n");
3609 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL\n");
3610 vogl_fprintf(pFile, "#undef DEF_PROTO_INTERNAL_VOID\n");
3611 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN_PARAMS\n");
3612 vogl_fprintf(pFile, "#undef DEF_FUNCTION_REFERENCE_PARAM\n");
3613 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_VALUE_PARAM\n");
3614 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_ARRAY_PARAM\n");
3615 vogl_fprintf(pFile, "#undef DEF_FUNCTION_IN_REFERENCE_PARAM\n");
3616 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUT_REFERENCE_PARAM\n");
3617 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUT_ARRAY_PARAM\n");
3618 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END_PARAMS\n");
3619 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN\n");
3620 vogl_fprintf(pFile, "#undef DEF_FUNCTION_BEGIN_VOID\n");
3621 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INIT\n");
3622 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INIT_VOID\n");
3623 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_VALUE_PARAM\n");
3624 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_REFERENCE_PARAM\n");
3625 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INPUT_ARRAY_PARAM\n");
3626 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUTPUT_REFERENCE_PARAM\n");
3627 vogl_fprintf(pFile, "#undef DEF_FUNCTION_OUTPUT_ARRAY_PARAM\n");
3628 vogl_fprintf(pFile, "#undef DEF_FUNCTION_CALL_GL\n");
3629 vogl_fprintf(pFile, "#undef DEF_FUNCTION_CALL_GL_VOID\n");
3630 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END\n");
3631 vogl_fprintf(pFile, "#undef DEF_FUNCTION_END_VOID\n");
3632 vogl_fprintf(pFile, "#undef DEF_FUNCTION_RETURN_PARAM\n");
3633 vogl_fprintf(pFile, "#undef DEF_FUNCTION_PARAM_COMPUTE_ARRAY_SIZE_GL_ENUM\n");
3634 vogl_fprintf(pFile, "#undef DEF_FUNCTION_INFO\n");
3637 struct gl_type_alias_t
3639 const char *m_pName;
3640 const char *m_pAlias;
3643 //-----------------------------------------------------------------------------------------------------------------------
3645 //-----------------------------------------------------------------------------------------------------------------------
3646 static dynamic_string_array purify_gl_type(dynamic_string str)
3648 static const gl_type_alias_t g_gl_type_comparison_exception_table[] =
3650 { "__GLXextFuncPtr", "void *" },
3651 { "GLfunction", "void *" },
3652 { "GLuint*", "unsigned int *" },
3653 { "GLuint *", "unsigned int *" },
3654 { "GLuint", "unsigned int" },
3656 { "GLboolean", "bool" },
3657 { "GLvoid", "void" },
3658 { "int64_t", "int64_t" },
3659 { "GLint64", "int64_t" },
3660 { "GLvoid*", "void*" },
3661 { "handleARB", "GLhandleARB" },
3663 { "const GLubyte *", "const char *" },
3664 { "GLubyte *", "char *" },
3665 { "GLubyte*", "char *" },
3666 { "GLchar*", "char *" },
3667 { "GLchar* const", "char *" },
3668 { "const char *", "char *" },
3669 { "GLchar", "char" },
3670 { "void function()", "void *" },
3671 { "int32_t", "int" },
3672 { "GLclampf", "float" },
3673 { "GLfloat", "float" },
3674 { "GLclampd", "double" },
3675 { "GLdouble", "double" },
3676 { "GLsizei", "int" },
3677 { "int32_t *", "int *" },
3678 { "int64_t *", "int64_t *" },
3679 { "GLint64*", "int64_t *" },
3680 { "GLint32*", "int *" },
3681 { "GLint32 *", "int *" },
3682 { "const GLuint*", "const unsigned int *" },
3683 { "const GLuint *", "const unsigned int *" },
3684 { "GLuint32*", "unsigned int *" },
3685 { "GLuint32 *", "unsigned int *" },
3686 { "GLulong*", "unsigned long *" },
3687 { "GLint*", "int *" },
3688 { "GLint *", "int *" },
3689 { "const GLint *", "const int *" },
3690 { "const GLvoid *", "const void *" },
3691 { "const GLvoid*", "const void *" },
3692 { "GLvoid *", "void *" },
3693 { "GLvoid*", "void *" },
3694 { "GLchar *", "char *" },
3695 { "GLchar*", "char *" },
3696 { "const GLchar *", "const char *" },
3697 { "const GLchar*", "const char *" },
3698 { "GLcharARB *", "char *" },
3699 { "GLcharARB*", "char *" },
3700 { "const GLcharARB *", "const char *" },
3701 { "const GLcharARB*", "const char *" },
3702 { "uint *", "unsigned int *" },
3703 { "ulong", "unsigned long" },
3704 { "ulong *", "unsigned long *" },
3705 { "GLuint64", "unsigned int64_t" },
3706 { "GLuint64*", "unsigned int64_t *" },
3707 { "const GLuint64*", "const unsigned int64_t *" },
3708 { "GLuint64EXT", "unsigned int64_t" },
3709 { "const GLuint64EXT *", "const unsigned int64_t *" },
3710 { "GLuint64EXT *", "unsigned int64_t *" },
3711 { "GLint64", "int64_t" },
3712 { "GLint64*", "int64_t *" },
3713 { "const GLint64*", "const int64_t *" },
3714 { "GLint64EXT", "int64_t" },
3715 { "const GLint64EXT *", "const int64_t *" },
3716 { "GLint64EXT *", "int64_t *" },
3717 { "GLintptr", "int *" },
3718 { "GLintptrARB", "int *" },
3719 { "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.
3720 { "GLhalfNV", "GLhalf" },
3721 { "const GLhalfNV *", "const GLhalf *" },
3722 { "GLchar* const *", "char * const *" },
3723 { "GLchar **", "char **" },
3724 { "const GLfloat *", "const float *" },
3725 { "const GLdouble *", "const double *" },
3726 { "GLfloat *", "float *" },
3727 { "const GLfloat *", "const float *" },
3728 { "GLfloat*", "float *" },
3729 { "const GLfloat *", "const float *" },
3730 { "const GLfloat*", "const float *" },
3731 { "GLclampf *", "float *" },
3732 { "const GLclampf *", "const float *" },
3733 { "GLclampf*", "float *" },
3734 { "GLdouble *", "double *" },
3735 { "GLdouble*", "double *" },
3736 { "GLclampd *", "double *" },
3737 { "GLclampd*", "double *" },
3738 { "GLsizeiptrARB", "GLsizeiptr" },
3739 { "handleARB*", "GLhandleARB *" },
3740 { "const GLcharARB* *", "const char **" },
3741 { "GLchar * *", "const char **" },
3742 { "GLchar**", "const char **" },
3743 { "const GLchar* *", "const char **" },
3744 { "GLoint", "unsigned int" }, // Bad in scraped XML
3745 { "const GLchar * *", "const char **" },
3746 { "cl_context", "struct _cl_context *" }, // Correct in spec, bad in scraped XML.
3747 { "cl_event", "struct _cl_event *" }, // Correct in spec, bad in scraped XML.
3750 // See if the ctype can be aliased to a simpler, hopefully equivalent ctype.
3751 for (uint i = 0; i < VOGL_ARRAY_SIZE(g_gl_type_comparison_exception_table); i++)
3753 if (str == g_gl_type_comparison_exception_table[i].m_pName)
3755 str = g_gl_type_comparison_exception_table[i].m_pAlias;
3760 // Tokenize type string
3761 dynamic_string_array tokens;
3762 str.tokenize(" \t", tokens, true);
3764 // Kill all const crap, nobody seems to agree on it so screw it.
3765 for (int i = 0; i < static_cast<int>(tokens.size()); i++)
3767 if (tokens[i] == "const")
3774 // Seperate out trailing "*" chars into multiple tokens.
3775 dynamic_string ptr_str("*");
3777 for (int i = 0; i < static_cast<int>(tokens.size()); i++)
3781 if (tokens[i].get_len() == 1)
3784 int pointer_ofs = tokens[i].find_right('*');
3785 if (pointer_ofs < 0)
3788 tokens[i].truncate(pointer_ofs);
3789 tokens.insert(i + 1, ptr_str);
3796 //-----------------------------------------------------------------------------------------------------------------------
3797 // validate_functions
3798 //-----------------------------------------------------------------------------------------------------------------------
3799 bool validate_functions(const gl_function_specs &gl_xml_funcs, const gl_function_specs &gl_funcs, const apitrace_func_specs &apitrace_gl_funcs,
3800 const gl_types &primary_typemap, const gl_types &alt_typemap) const
3802 dynamic_string_array missing_funcs;
3804 uint total_skipped = 0;
3805 uint total_validated = 0;
3806 uint total_failures = 0;
3807 uint total_not_found = 0;
3809 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
3811 const gl_function_def &func = gl_funcs[func_index];
3813 // 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),
3814 // or they have been manually validated to be correct in the .spec files.
3815 if ((func.m_name == "Uniform2ui") || (func.m_name == "Uniform3ui") || (func.m_name == "Uniform4ui") ||
3816 (func.m_name == "ProgramUniform2ui") || (func.m_name == "ProgramUniform3ui") || (func.m_name == "ProgramUniform4ui") ||
3817 (func.m_name == "ReplacementCodePointerSUN") || (func.m_name == "ClearDepthfOES") || (func.m_name == "QueryMatrixxOES") ||
3818 (func.m_name == "QueryMatrixxOES") || (func.m_name == "SendPbufferToVideoNV") || (func.m_name == "ReleaseVideoImageNV") ||
3819 (func.m_name == "BindVideoImageNV") || (func.m_name == "GetTransparentIndexSUN") ||
3820 (func.m_name == "GetIntegerui64i_vNV"))
3826 const gl_types *pPrimary_typemap = &primary_typemap;
3827 const gl_types *pAlt_typemap = &alt_typemap;
3828 if ((func.m_lib == cGLX) || (func.m_lib == cWGL))
3829 std::swap(pPrimary_typemap, pAlt_typemap);
3831 dynamic_string return_type;
3832 if (func.m_return == "void")
3834 return_type = "void";
3838 const dynamic_string *pCType = pPrimary_typemap->find(func.m_return);
3840 pCType = pAlt_typemap->find(func.m_return);
3843 console::warning("Unable to map spec type %s\n", func.m_return.get_ptr());
3847 return_type = *pCType;
3850 dynamic_string_array func_param_ctypes;
3852 for (uint param_index = 0; param_index < func.m_params.size(); param_index++)
3854 const gl_function_param ¶m = func.m_params[param_index];
3856 const dynamic_string *pCType = pPrimary_typemap->find(param.m_type);
3858 pCType = pAlt_typemap->find(param.m_type);
3861 console::warning("Unable to map spec type %s\n", param.m_type.get_ptr());
3865 dynamic_string type_prefix;
3867 dynamic_string type_suffix("");
3868 if ((param.m_semantic == "array") || (param.m_semantic == "reference"))
3872 if (param.m_direction == "in")
3874 if (!pCType->ends_with("const"))
3875 type_prefix = "const ";
3879 dynamic_string full_ctype(cVarArg, "%s%s%s", type_prefix.get_ptr(), pCType->get_ptr(), type_suffix.get_ptr());
3881 func_param_ctypes.push_back(full_ctype);
3884 const apitrace_gl_func_def *pApitrace_func_def = apitrace_gl_funcs.find(func.m_full_name.get_ptr());
3885 if (pApitrace_func_def)
3887 if (pApitrace_func_def->m_return_gl_type != return_type)
3889 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());
3893 if (pApitrace_func_def->m_params.size() != func_param_ctypes.size())
3895 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());
3900 for (uint i = 0; i < func_param_ctypes.size(); i++)
3902 const apitrace_gl_func_param_def ¶m_def = pApitrace_func_def->m_params[i];
3904 dynamic_string apitrace_param_type(param_def.m_gl_type);
3906 dynamic_string_array purified_spec_ctype(purify_gl_type(func_param_ctypes[i]));
3907 dynamic_string_array purified_apitrace_ctype(purify_gl_type(apitrace_param_type));
3909 bool type_mismatch = purified_spec_ctype.size() != purified_apitrace_ctype.size();
3912 for (uint j = 0; j < purified_spec_ctype.size(); j++)
3914 if (purified_spec_ctype[j] != purified_apitrace_ctype[j])
3916 type_mismatch = true;
3924 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());
3927 //printf(" { \"%s\", \"%s\" },\n", func_param_ctypes[i].get_ptr(), apitrace_param_type.get_ptr());
3934 //printf("Func not found in apitrace specs: %s\n", func.m_full_name.get_ptr());
3937 uint gl_xml_func_index;
3938 for (gl_xml_func_index = 0; gl_xml_func_index < gl_xml_funcs.size(); gl_xml_func_index++)
3940 if (gl_xml_funcs[gl_xml_func_index].m_lib != func.m_lib)
3943 dynamic_string gl_xml_func_name(gl_xml_funcs[gl_xml_func_index].m_name);
3945 if (gl_xml_func_name == func.m_name)
3949 if (gl_xml_func_index == gl_xml_funcs.size())
3951 dynamic_string suffix;
3952 if (func.m_name.ends_with("ARB", true) || func.m_name.ends_with("EXT", true))
3953 suffix.set(func.m_name).right(func.m_name.get_len() - 3);
3954 else if (func.m_name.ends_with("NV", true))
3955 suffix.set(func.m_name).right(func.m_name.get_len() - 2);
3957 if (suffix.get_len())
3959 for (gl_xml_func_index = 0; gl_xml_func_index < gl_xml_funcs.size(); gl_xml_func_index++)
3961 if (gl_xml_funcs[gl_xml_func_index].m_lib != func.m_lib)
3964 dynamic_string gl_xml_func_name(gl_xml_funcs[gl_xml_func_index].m_name);
3965 gl_xml_func_name += suffix;
3967 if (gl_xml_func_name == func.m_name)
3972 if (gl_xml_func_index == gl_xml_funcs.size())
3974 missing_funcs.push_back(func.m_name);
3980 const gl_function_def &xml_func = gl_xml_funcs[gl_xml_func_index];
3981 if (xml_func.m_params.size() != func.m_params.size())
3983 console::error("Function %s param number mismatch\n", func.m_name.get_ptr());
3988 dynamic_string_array purified_func_return(purify_gl_type(return_type));
3990 dynamic_string xml_func_return(xml_func.m_return);
3992 // XML exceptions (they where incorrect on the web, GLsync here makes no sense)
3993 if ((func.m_name == "FramebufferRenderbuffer") || (func.m_name == "FlushMappedBufferRange"))
3995 xml_func_return = "void";
3998 dynamic_string_array purified_xml_func_return(purify_gl_type(xml_func_return));
4000 if (purified_func_return.size() != purified_xml_func_return.size())
4002 console::warning("Function %s return type mismatch: \"%s\" != \"%s\"\n", func.m_name.get_ptr(), return_type.get_ptr(), xml_func_return.get_ptr());
4007 for (uint i = 0; i < purified_func_return.size(); i++)
4009 if (purified_func_return[i] != purified_xml_func_return[i])
4011 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());
4018 for (param_index = 0; param_index < func.m_params.size(); param_index++)
4020 dynamic_string param_type(func_param_ctypes[param_index]);
4021 dynamic_string xml_param_type(xml_func.m_params[param_index].m_type);
4023 // manual XML exceptions (incorrect on the web)
4024 if ((param_index == 4) && (func.m_name == "GetTransformFeedbackVarying"))
4026 xml_param_type = "GLsizei *";
4028 if ((param_index == 3) && (func.m_name == "GetActiveUniformBlockiv"))
4030 xml_param_type = "GLint *";
4032 if ((param_index == 1) && (func.m_name == "CreateContextAttribsARB"))
4034 xml_param_type = "GLXFBConfig";
4036 if ((param_index == 3) && (func.m_name == "ProgramNamedParameter4fvNV"))
4038 xml_param_type = "GLfloat *";
4040 if ((param_index == 3) && (func.m_name == "ProgramNamedParameter4dvNV"))
4042 xml_param_type = "GLdouble *";
4045 dynamic_string_array purified_param_type(purify_gl_type(param_type));
4046 dynamic_string_array purified_xml_param_type(purify_gl_type(xml_param_type));
4048 if (purified_param_type.size() != purified_xml_param_type.size())
4050 console::warning("Function %s param type mismatch: \"%s\" != \"%s\"\n", func.m_name.get_ptr(), param_type.get_ptr(), xml_param_type.get_ptr());
4055 for (uint j = 0; j < purified_param_type.size(); j++)
4057 if (purified_param_type[j] != purified_xml_param_type[j])
4059 console::warning("Function %s param type mismatch: \"%s\" != \"%s\", param \"%s\" != \"%s\"\n", func.m_name.get_ptr(),
4060 param_type.get_ptr(),
4061 xml_param_type.get_ptr(),
4062 purified_param_type[j].get_ptr(),
4063 purified_xml_param_type[j].get_ptr());
4074 printf("Results of spec vs. XML function validation:\n");
4075 printf("Total passed: %u\n", total_validated);
4076 printf("Total failures: %u\n", total_failures);
4077 printf("Total skipped: %u\n", total_skipped);
4078 printf("Total functions present in spec but missing in XML: %u\n", total_not_found);
4080 if (g_command_line_params.get_value_as_bool("verbose"))
4082 printf("\nMissing function list:\n");
4083 for (uint i = 0; i < missing_funcs.size(); i++)
4084 printf("%s\n", missing_funcs[i].get_ptr());
4086 printf("\nMissing function list excluding OES and vendor suffixes:\n");
4087 for (uint i = 0; i < missing_funcs.size(); i++)
4089 const dynamic_string &func = missing_funcs[i];
4092 for (j = 0; j < VOGL_ARRAY_SIZE(g_gl_vendor_suffixes); j++)
4093 if (func.ends_with(g_gl_vendor_suffixes[j], true))
4096 if (j < VOGL_ARRAY_SIZE(g_gl_vendor_suffixes))
4099 printf("%s\n", func.get_ptr());
4106 //-----------------------------------------------------------------------------------------------------------------------
4107 // update_whitelisted_funcs
4108 //-----------------------------------------------------------------------------------------------------------------------
4109 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)
4111 VOGL_NOTE_UNUSED(unique_ctype_enums);
4112 VOGL_NOTE_UNUSED(pointee_types);
4114 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4116 vogl::vector<bool> used_flags(m_simple_replay_funcs.size());
4118 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4120 const gl_function_def &func_def = gl_funcs[func_index];
4121 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());
4124 for (i = 0; i < m_simple_replay_funcs.size(); i++)
4126 if (m_simple_replay_funcs[i].ends_with("*"))
4128 dynamic_string prefix(m_simple_replay_funcs[i]);
4129 prefix.left(prefix.get_len() - 1);
4130 if (full_func_name.begins_with(prefix.get_ptr()))
4135 if (full_func_name == m_simple_replay_funcs[i])
4140 if (i == m_simple_replay_funcs.size())
4143 VOGL_ASSERT(!used_flags[i]);
4144 used_flags[i] = true;
4146 if (whitelisted_funcs.find(full_func_name) < 0)
4148 console::printf("Adding simple GL replay func %s to func whitelist\n", full_func_name.get_ptr());
4149 whitelisted_funcs.push_back(full_func_name);
4153 console::warning("Simple GL replay func %s was already in the func whitelist\n", full_func_name.get_ptr());
4157 for (uint i = 0; i < m_simple_replay_funcs.size(); i++)
4160 console::warning("Simple replay func %s was not found/used\n", m_simple_replay_funcs[i].get_ptr());
4166 //-----------------------------------------------------------------------------------------------------------------------
4167 // generate_simple_replay_funcs
4168 //-----------------------------------------------------------------------------------------------------------------------
4169 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
4171 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4173 console::info("--- Generating \"gl_glx_simple_replay_funcs.inc\":\n");
4175 FILE *pFile = vogl_fopen("gl_glx_simple_replay_funcs.inc", "w");
4178 console::error("Failed creating file gl_glx_simple_replay_funcs.inc\n");
4182 dump_inc_file_header(pFile);
4184 vogl::vector<bool> used_flags(m_simple_replay_funcs.size());
4186 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4188 const gl_function_def &func_def = gl_funcs[func_index];
4189 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());
4192 for (i = 0; i < m_simple_replay_funcs.size(); i++)
4194 if (m_simple_replay_funcs[i].ends_with("*"))
4196 dynamic_string prefix(m_simple_replay_funcs[i]);
4197 prefix.left(prefix.get_len() - 1);
4198 if (full_func_name.begins_with(prefix.get_ptr()))
4203 if (full_func_name == m_simple_replay_funcs[i])
4208 if (i == m_simple_replay_funcs.size())
4211 VOGL_ASSERT(!used_flags[i]);
4212 used_flags[i] = true;
4214 vogl_fprintf(pFile, "VOGL_SIMPLE_REPLAY_FUNC_BEGIN(%s, func_def.m_params.size())\n", full_func_name.get_ptr());
4216 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4218 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4220 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4222 gl_string_map::const_iterator it = pointee_types.find(func_def.m_params[param_index].m_ctype_enum);
4223 if (it == pointee_types.end())
4225 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4230 it = unique_ctype_enums.find(it->second);
4231 if (it == unique_ctype_enums.end())
4233 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4238 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_CLIENT_MEMORY(%s, %u)\n", it->second.get_ptr(), param_index);
4242 // TODO: Add expected size of buffer check
4243 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_VALUE(%s, %u)\n", func_def.m_params[param_index].m_ctype.get_ptr(), param_index);
4247 vogl_fprintf(pFile, " VOGL_SIMPLE_REPLAY_FUNC_PARAM_SEPERATOR\n");
4250 vogl_fprintf(pFile, "VOGL_SIMPLE_REPLAY_FUNC_END(%s)\n\n", full_func_name.get_ptr());
4258 //-----------------------------------------------------------------------------------------------------------------------
4259 // generate_replay_func_load_macros
4260 //-----------------------------------------------------------------------------------------------------------------------
4261 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
4263 VOGL_NOTE_UNUSED(unique_ctype_enums);
4264 VOGL_NOTE_UNUSED(pointee_types);
4266 dynamic_string_array new_whitelisted_funcs(whitelisted_funcs);
4268 console::info("--- Generating \"gl_glx_replay_helper_macros.inc\":\n");
4270 FILE *pFile = vogl_fopen("gl_glx_replay_helper_macros.inc", "w");
4273 console::error("Failed creating file gl_glx_replay_helper_macros\n");
4277 dump_inc_file_header(pFile);
4279 for (uint func_index = 0; func_index < gl_funcs.size(); func_index++)
4281 const gl_function_def &func_def = gl_funcs[func_index];
4282 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());
4284 vogl_fprintf(pFile, "#define VOGL_REPLAY_LOAD_PARAMS_HELPER_%s %c\n", full_func_name.get_ptr(), func_def.m_params.size() ? '\\' : ' ');
4286 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4288 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4290 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4293 gl_string_map::const_iterator it = pointee_types.find(func_def.m_params[param_index].m_ctype_enum);
4294 if (it == pointee_types.end())
4296 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4301 it = unique_ctype_enums.find(it->second);
4302 if (it == unique_ctype_enums.end())
4304 console::error("Failed finding pointee ctype for ctype %s\n", func_def.m_params[param_index].m_ctype.get_ptr());
4310 dynamic_string const_str;
4311 if (!func_def.m_params[param_index].m_ctype.begins_with("const "))
4312 const_str = "const ";
4314 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);
4318 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);
4322 vogl_fprintf(pFile, " \\\n");
4324 vogl_fprintf(pFile, "\n");
4327 vogl_fprintf(pFile, "\n");
4329 vogl_fprintf(pFile, "#define VOGL_REPLAY_CALL_GL_HELPER_%s GL_ENTRYPOINT(%s)(", full_func_name.get_ptr(), full_func_name.get_ptr());
4331 for (uint param_index = 0; param_index < func_def.m_params.size(); param_index++)
4333 const bool last_param = (param_index == (func_def.m_params.size() - 1));
4335 if (func_def.m_params[param_index].m_ctype_enum.ends_with("_PTR"))
4337 if (func_def.m_params[param_index].m_ctype_enum.begins_with("VOGL_CONST_"))
4338 vogl_fprintf(pFile, "pTrace_%s", func_def.m_params[param_index].m_name.get_ptr());
4340 vogl_fprintf(pFile, "pReplay_%s", func_def.m_params[param_index].m_name.get_ptr());
4344 vogl_fprintf(pFile, "%s", func_def.m_params[param_index].m_name.get_ptr());
4348 vogl_fprintf(pFile, ", ");
4351 vogl_fprintf(pFile, ")\n\n");
4359 //-----------------------------------------------------------------------------------------------------------------------
4360 // read_regex_function_array
4361 //-----------------------------------------------------------------------------------------------------------------------
4362 bool read_regex_function_array(const char *pFilename, dynamic_string_array &funcs)
4364 dynamic_string_array regex_func_patterns;
4366 if (!file_utils::read_text_file(pFilename, regex_func_patterns, file_utils::cRTFTrim | file_utils::cRTFIgnoreEmptyLines | file_utils::cRTFIgnoreCommentedLines | file_utils::cRTFPrintErrorMessages))
4369 regex_func_patterns.unique(dynamic_string_equal_to_case_sensitive());
4371 vogl::vector<bool> used_flags(regex_func_patterns.size());
4373 for (uint i = 0; i < m_all_gl_funcs.size(); i++)
4376 for (j = 0; j < regex_func_patterns.size(); j++)
4377 if (regexp_full_match(m_all_gl_funcs[i].m_full_name.get_ptr(), regex_func_patterns[j].get_ptr()))
4380 if (j < regex_func_patterns.size())
4382 funcs.push_back(m_all_gl_funcs[i].m_full_name);
4383 used_flags[j] = true;
4387 for (uint i = 0; i < used_flags.size(); i++)
4389 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);
4395 //----------------------------------------------------------------------------------------------------------------------
4396 // init_command_line_params
4397 //----------------------------------------------------------------------------------------------------------------------
4398 static bool init_command_line_params(int argc, char *argv[])
4400 command_line_params::parse_config parse_cfg;
4401 parse_cfg.m_single_minus_params = true;
4402 parse_cfg.m_double_minus_params = true;
4404 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))
4406 console::error("%s: Failed parsing command line parameters!\n", VOGL_FUNCTION_NAME);
4413 //-----------------------------------------------------------------------------------------------------------------------
4415 //-----------------------------------------------------------------------------------------------------------------------
4416 static bool check_for_option(int argc, char *argv[], const char *pOption)
4418 for (int i = 1; i < argc; i++)
4420 if ((argv[i][0] == '/') || (argv[i][0] == '-'))
4422 if (vogl_stricmp(&argv[i][1], pOption) == 0)
4429 //-----------------------------------------------------------------------------------------------------------------------
4431 //-----------------------------------------------------------------------------------------------------------------------
4432 static void print_title()
4434 console::printf("voglgen");
4435 console::printf(" %s Built %s, %s", vogl_is_x64() ? "x64" : "x86", __DATE__, __TIME__);
4436 #ifdef VOGL_BUILD_DEBUG
4437 console::printf(" DEBUG build");
4439 console::printf("\n");
4440 console::printf("Debugger present: %u\n", vogl_is_debugger_present());
4443 //-------------------------------------------------------------------------------------------------------------------------------
4445 //-------------------------------------------------------------------------------------------------------------------------------
4446 static int main_internal(int argc, char *argv[])
4448 VOGL_NOTE_UNUSED(argc);
4449 VOGL_NOTE_UNUSED(argv);
4453 colorized_console::init();
4454 colorized_console::set_exception_callback();
4456 if (check_for_option(argc, argv, "quiet"))
4457 console::disable_output();
4461 bool status = false;
4462 if (init_command_line_params(argc, argv))
4464 dynamic_string srcdir;
4466 if (g_command_line_params.get_value_as_string(srcdir, "srcdir"))
4468 printf("srcdir: '%s'\n", srcdir.get_ptr());
4469 chdir(srcdir.get_ptr());
4471 // If we can't find this text file, try the vogl/glspec dir.
4472 if (access("apitrace_gl_param_info.txt", F_OK) != 0)
4474 if (access("../../vogl/glspec/apitrace_gl_param_info.txt", F_OK) == 0)
4475 chdir("../../vogl/glspec");
4477 getcwd(cwd, sizeof(cwd));
4478 printf("Current working directory: %s\n\n", cwd);
4482 console::printf("---------------- Begin Generator Init\n");
4483 status = generator.init();
4484 console::printf("---------------- End Generator Init\n");
4488 dynamic_string regex_pattern;
4489 if (g_command_line_params.get_value_as_string(regex_pattern, "func_regex"))
4490 generator.func_regex(regex_pattern.get_ptr());
4491 else if (g_command_line_params.get_value_as_string(regex_pattern, "param_regex"))
4492 generator.param_regex(regex_pattern.get_ptr());
4493 else if (g_command_line_params.get_value_as_string(regex_pattern, "category_regex"))
4494 generator.category_regex(regex_pattern.get_ptr());
4495 else if (g_command_line_params.get_value_as_string(regex_pattern, "namespace_regex"))
4496 generator.namespace_regex(regex_pattern.get_ptr());
4497 else if (g_command_line_params.get_value_as_string(regex_pattern, "ctype_regex"))
4498 generator.ctype_regex(regex_pattern.get_ptr());
4501 console::printf("---------------- Begin Generate\n");
4502 status = generator.generate();
4503 console::printf("---------------- End Generate\n");
4505 if (status && g_command_line_params.get_value_as_bool("debug"))
4507 console::printf("---------------- Begin Debug Dump\n");
4508 generator.dump_debug_files();
4509 console::printf("---------------- End Debug Dump\n");
4516 console::error("voglgen FAILED!\n");
4518 console::printf("voglgen succeeded\n (to %s)\n", cwd);
4520 int exit_status = status ? EXIT_SUCCESS : EXIT_FAILURE;
4522 console::printf("%u warning(s), %u error(s)\n", console::get_total_messages(cWarningConsoleMessage), console::get_total_messages(cErrorConsoleMessage));
4524 console::printf("Exit status: %i\n", exit_status);
4526 colorized_console::deinit();
4528 vogl_print_heap_stats();
4530 return status ? EXIT_SUCCESS : EXIT_FAILURE;
4533 //-----------------------------------------------------------------------------------------------------------------------
4535 //-----------------------------------------------------------------------------------------------------------------------
4536 static void pause_and_wait(void)
4538 console::enable_output();
4540 console::message("\nPress a key to continue.\n");
4544 if (vogl_getch() != -1)
4549 //-----------------------------------------------------------------------------------------------------------------------
4551 //-----------------------------------------------------------------------------------------------------------------------
4552 int main(int argc, char *argv[])
4554 int status = EXIT_FAILURE;
4556 if (vogl_is_debugger_present())
4558 status = main_internal(argc, argv);
4565 status = main_internal(argc, argv);
4567 __except(EXCEPTION_EXECUTE_HANDLER)
4569 console::error("Uncached exception! voglgen command line tool failed!\n");
4572 status = main_internal(argc, argv);
4576 if (check_for_option(argc, argv, "pause"))
4578 if ((status == EXIT_FAILURE) || (console::get_total_messages(cErrorConsoleMessage)))