summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Justen <jordan.l.justen@intel.com>2022-12-28 13:26:34 -0800
committerMarge Bot <emma+marge@anholt.net>2023-08-06 20:44:59 +0000
commitb4c8d2dc45554fc61250f58bf0a2678d90ea6769 (patch)
treee31a797d96fef3044f08959c1c402018b85bde0f
parent1d5535613e6476c6fe1ac1efb0f97371afc77db5 (diff)
intel/decoder: Add intel_spec_load_common()
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20889>
-rw-r--r--src/intel/common/intel_decoder.c210
1 files changed, 116 insertions, 94 deletions
diff --git a/src/intel/common/intel_decoder.c b/src/intel/common/intel_decoder.c
index 42a8f8e5c4f..7a47cbaced2 100644
--- a/src/intel/common/intel_decoder.c
+++ b/src/intel/common/intel_decoder.c
@@ -21,6 +21,7 @@
* IN THE SOFTWARE.
*/
+#include <libgen.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
@@ -31,6 +32,7 @@
#include <zlib.h>
#include <util/macros.h>
+#include <util/os_file.h>
#include <util/ralloc.h>
#include <util/u_math.h>
@@ -592,18 +594,34 @@ intel_spec_init(void)
return spec;
}
-struct intel_spec *
-intel_spec_load(const struct intel_device_info *devinfo)
+static bool
+get_xml_data_dir(const char *dirname, const char *filename,
+ void **data, size_t *data_len)
+{
+ size_t fullname_len = strlen(dirname) + strlen(filename) + 2;
+ char *fullname = malloc(fullname_len);
+
+ if (fullname == NULL)
+ return NULL;
+
+ ASSERTED size_t len = snprintf(fullname, fullname_len, "%s/%s",
+ dirname, filename);
+ assert(len < fullname_len);
+
+ *data = (void*)os_read_file(fullname, data_len);
+ free(fullname);
+ return *data != NULL;
+}
+
+static bool
+get_embedded_xml_data(int verx10, void **data, size_t *data_len)
{
- struct parser_context ctx;
- void *buf;
uint8_t *text_data = NULL;
uint32_t text_offset = 0, text_length = 0;
ASSERTED uint32_t total_length;
- uint32_t ver_10 = devinfo->verx10;
for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) {
- if (genxml_files_table[i].ver_10 == ver_10) {
+ if (genxml_files_table[i].ver_10 == verx10) {
text_offset = genxml_files_table[i].offset;
text_length = genxml_files_table[i].length;
break;
@@ -611,25 +629,8 @@ intel_spec_load(const struct intel_device_info *devinfo)
}
if (text_length == 0) {
- fprintf(stderr, "unable to find gen (%u) data\n", ver_10);
- return NULL;
- }
-
- memset(&ctx, 0, sizeof ctx);
- ctx.parser = XML_ParserCreate(NULL);
- XML_SetUserData(ctx.parser, &ctx);
- if (ctx.parser == NULL) {
- fprintf(stderr, "failed to create parser\n");
- return NULL;
- }
-
- XML_SetElementHandler(ctx.parser, start_element, end_element);
- XML_SetCharacterDataHandler(ctx.parser, character_data);
-
- ctx.spec = intel_spec_init();
- if (ctx.spec == NULL) {
- fprintf(stderr, "Failed to create intel_spec\n");
- return NULL;
+ fprintf(stderr, "unable to find gen (%u) data\n", verx10);
+ return false;
}
total_length = zlib_inflate(compress_genxmls,
@@ -637,117 +638,138 @@ intel_spec_load(const struct intel_device_info *devinfo)
(void **) &text_data);
assert(text_offset + text_length <= total_length);
- buf = XML_GetBuffer(ctx.parser, text_length);
- memcpy(buf, &text_data[text_offset], text_length);
+ *data = malloc(text_length);
+ if (*data == NULL)
+ return false;
- if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) {
- fprintf(stderr,
- "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n",
- XML_GetCurrentLineNumber(ctx.parser),
- XML_GetCurrentColumnNumber(ctx.parser),
- XML_GetCurrentByteIndex(ctx.parser), text_length,
- XML_ErrorString(XML_GetErrorCode(ctx.parser)));
- XML_ParserFree(ctx.parser);
- free(text_data);
- return NULL;
+ memcpy(*data, &text_data[text_offset], text_length);
+ free(text_data);
+ *data_len = text_length;
+ return true;
+}
+
+static bool
+get_embedded_xml_data_by_name(const char *filename,
+ void **data, size_t *data_len)
+{
+ int filename_len = strlen(filename);
+ if (filename_len < 8 || filename_len > 10)
+ return false;
+
+ if (strncmp(filename, "gen", 3) != 0 ||
+ strcmp(filename + filename_len - 4, ".xml") != 0)
+ return false;
+
+ char *numstr = strndup(filename + 3, filename_len - 7);
+ char *endptr;
+ long num = strtol(numstr, &endptr, 10);
+ if (*endptr != '\0') {
+ free(numstr);
+ return false;
}
+ /* convert ver numbers to verx10 */
+ if (num < 45)
+ num = num * 10;
- XML_ParserFree(ctx.parser);
- free(text_data);
+ free(numstr);
+ return get_embedded_xml_data(num, data, data_len);
+}
- return ctx.spec;
+static bool
+get_xml_data(int verx10, const char *dirname, const char *filename,
+ void **data, size_t *data_len)
+{
+ if (dirname != NULL)
+ return get_xml_data_dir(dirname, filename, data, data_len);
+ else if (filename != NULL)
+ return get_embedded_xml_data_by_name(filename, data, data_len);
+ else
+ return get_embedded_xml_data(verx10, data, data_len);
}
-struct intel_spec *
-intel_spec_load_filename(const char *filename)
+static struct intel_spec *
+intel_spec_load_common(int verx10, const char *dirname, const char *filename)
{
struct parser_context ctx;
- FILE *input;
- void *buf;
- size_t len;
+ void *xmlbuf, *data;
+ size_t data_len;
- input = fopen(filename, "r");
- if (input == NULL) {
- fprintf(stderr, "failed to open xml description\n");
+ if (!get_xml_data(verx10, dirname, filename, &data, &data_len))
return NULL;
- }
memset(&ctx, 0, sizeof ctx);
ctx.parser = XML_ParserCreate(NULL);
XML_SetUserData(ctx.parser, &ctx);
if (ctx.parser == NULL) {
+ free(data);
fprintf(stderr, "failed to create parser\n");
- fclose(input);
return NULL;
}
XML_SetElementHandler(ctx.parser, start_element, end_element);
XML_SetCharacterDataHandler(ctx.parser, character_data);
- ctx.loc.filename = filename;
ctx.spec = intel_spec_init();
if (ctx.spec == NULL) {
+ free(data);
fprintf(stderr, "Failed to create intel_spec\n");
- goto end;
+ return NULL;
}
- do {
- buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
- len = fread(buf, 1, XML_BUFFER_SIZE, input);
- if (ferror(input)) {
- fprintf(stderr, "fread: %m\n");
- intel_spec_destroy(ctx.spec);
- ctx.spec = NULL;
- goto end;
- } else if (len == 0 && feof(input))
- goto end;
+ xmlbuf = XML_GetBuffer(ctx.parser, data_len);
+ memcpy(xmlbuf, data, data_len);
+ free(data);
+ data = NULL;
- if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
- fprintf(stderr,
- "Error parsing XML at line %ld col %ld: %s\n",
- XML_GetCurrentLineNumber(ctx.parser),
- XML_GetCurrentColumnNumber(ctx.parser),
- XML_ErrorString(XML_GetErrorCode(ctx.parser)));
- intel_spec_destroy(ctx.spec);
- ctx.spec = NULL;
- goto end;
- }
- } while (len > 0);
-
- end:
- XML_ParserFree(ctx.parser);
-
- fclose(input);
-
- /* free ctx.spec if genxml is empty */
- if (ctx.spec &&
- _mesa_hash_table_num_entries(ctx.spec->commands) == 0 &&
- _mesa_hash_table_num_entries(ctx.spec->structs) == 0) {
+ if (XML_ParseBuffer(ctx.parser, data_len, true) == 0) {
fprintf(stderr,
- "Error parsing XML: empty spec.\n");
- intel_spec_destroy(ctx.spec);
+ "Error parsing XML at line %ld col %ld byte %ld/%zu: %s\n",
+ XML_GetCurrentLineNumber(ctx.parser),
+ XML_GetCurrentColumnNumber(ctx.parser),
+ XML_GetCurrentByteIndex(ctx.parser), data_len,
+ XML_ErrorString(XML_GetErrorCode(ctx.parser)));
+ XML_ParserFree(ctx.parser);
return NULL;
}
+ XML_ParserFree(ctx.parser);
+
return ctx.spec;
}
struct intel_spec *
+intel_spec_load(const struct intel_device_info *devinfo)
+{
+ return intel_spec_load_common(devinfo->verx10, NULL, NULL);
+}
+
+struct intel_spec *
+intel_spec_load_filename(const char *filename)
+{
+ char *tmp = strdup(filename);
+ char *dir = strdup(dirname(tmp));
+ free(tmp);
+ tmp = strdup(filename);
+ char *base = strdup(basename(tmp));
+ free(tmp);
+ struct intel_spec *spec = intel_spec_load_common(0, dir, base);
+ free(dir);
+ free(base);
+ return spec;
+}
+
+struct intel_spec *
intel_spec_load_from_path(const struct intel_device_info *devinfo,
const char *path)
{
- size_t filename_len = strlen(path) + 20;
- char *filename = malloc(filename_len);
+ char filename[20];
int xml_file_num = devinfo->verx10 % 10 ? devinfo->verx10 : devinfo->ver;
- ASSERTED size_t len = snprintf(filename, filename_len, "%s/gen%i.xml",
- path, xml_file_num);
- assert(len < filename_len);
+ ASSERTED size_t len = snprintf(filename, ARRAY_SIZE(filename), "gen%i.xml",
+ xml_file_num);
+ assert(len < ARRAY_SIZE(filename));
- struct intel_spec *spec = intel_spec_load_filename(filename);
- free(filename);
-
- return spec;
+ return intel_spec_load_common(devinfo->verx10, path, filename);
}
void intel_spec_destroy(struct intel_spec *spec)