[waffle] [PATCH v2 4/4] wflinfo.c: Add a --json flag that prints json

baker.dylan.c at gmail.com baker.dylan.c at gmail.com
Tue Jan 5 11:46:53 PST 2016


From: Dylan Baker <baker.dylan.c at gmail.com>

This adds some code to print a JSON formatted version of data provided
by wflinfo.

Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>

v2: - Add -j short options (Frank)
    - Make context flags always an array (Chad)
    - Remove explicit returns from void functions (Chad)
    - Fix spaces around "*" in variable definitions
    - Nest waffle specific information in a waffle hash and OpenGL
      specific information in an OpenGL hash
    - use ARRAY_SIZE macro
    - rebase on previous changes
---
 src/utils/wflinfo.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 176 insertions(+), 2 deletions(-)

diff --git a/src/utils/wflinfo.c b/src/utils/wflinfo.c
index 8ee95c6..456f91b 100644
--- a/src/utils/wflinfo.c
+++ b/src/utils/wflinfo.c
@@ -85,6 +85,9 @@ static const char *usage_message =
     "    --debug-context\n"
     "        Create a debug context.\n"
     "\n"
+    "    -j, --json\n"
+    "        Print a JSON formatted summary.\n"
+    "\n"
     "    -h, --help\n"
     "        Print wflinfo usage information.\n"
     "\n"
@@ -104,6 +107,7 @@ enum {
     OPT_VERBOSE = 'v',
     OPT_DEBUG_CONTEXT,
     OPT_FORWARD_COMPATIBLE,
+    OPT_JSON = 'j',
     OPT_HELP = 'h',
 };
 
@@ -115,6 +119,7 @@ static const struct option get_opts[] = {
     { .name = "verbose",        .has_arg = no_argument,           .val = OPT_VERBOSE },
     { .name = "debug-context",  .has_arg = no_argument,           .val = OPT_DEBUG_CONTEXT },
     { .name = "forward-compatible", .has_arg = no_argument,       .val = OPT_FORWARD_COMPATIBLE },
+    { .name = "json",           .has_arg = no_argument,           .val = OPT_JSON },
     { .name = "help",           .has_arg = no_argument,           .val = OPT_HELP },
     { 0 },
 };
@@ -252,6 +257,8 @@ struct options {
 
     bool verbose;
 
+    bool json;
+
     bool context_forward_compatible;
     bool context_debug;
 
@@ -337,7 +344,7 @@ parse_args(int argc, char *argv[], struct options *opts)
     opterr = 0;
 
     while (loop_get_opt) {
-        int opt = getopt_long(argc, argv, "a:hp:vV:", get_opts, NULL);
+        int opt = getopt_long(argc, argv, "a:hp:vV:j", get_opts, NULL);
         switch (opt) {
             case -1:
                 loop_get_opt = false;
@@ -395,6 +402,9 @@ parse_args(int argc, char *argv[], struct options *opts)
             case OPT_DEBUG_CONTEXT:
                 opts->context_debug = true;
                 break;
+            case OPT_JSON:
+                opts->json = true;
+                break;
             case OPT_HELP:
                 write_usage_and_exit(stdout, EXIT_SUCCESS);
                 break;
@@ -563,6 +573,165 @@ print_context_flags(void)
     printf("\n");
 }
 
+static void
+json_print_context_flags(void)
+{
+    const int flag_count = ARRAY_SIZE(context_flags);
+    GLint gl_context_flags = 0;
+
+    printf("        \"context flags\": ");
+
+    glGetIntegerv(GL_CONTEXT_FLAGS, &gl_context_flags);
+    if (glGetError() != GL_NO_ERROR) {
+        printf("\"WFLINFO_GL_ERROR\"\n");
+        return;
+    }
+
+    if (gl_context_flags == 0) {
+        printf("[]");
+        return;
+    }
+
+    printf("[\n");
+    for (int i = 0; i < flag_count; i++) {
+        if ((context_flags[i].flag & gl_context_flags) != 0) {
+            printf("        \"%s\"", context_flags[i].str);
+            gl_context_flags = gl_context_flags & ~context_flags[i].flag;
+            if (i != flag_count) {
+                printf(",\n");
+            }
+        }
+    }
+    for (int i = 0; gl_context_flags != 0; gl_context_flags >>= 1, i++) {
+        if ((gl_context_flags & 1) != 0) {
+            printf(",\n");
+            printf("        0x%x", 1 << i);
+        }
+    }
+    printf("    ]");
+}
+
+static void
+json_print_extensions(bool use_stringi)
+{
+    // Print extensions in JSON format
+    printf("        \"extensions\": [\n");
+    if (use_stringi) {
+        GLint count = 0, i;
+        const char *ext;
+
+        glGetIntegerv(GL_NUM_EXTENSIONS, &count);
+        if (glGetError() != GL_NO_ERROR) {
+            printf("\"WFLINFO_GL_ERROR\"");
+        } else {
+            for (i = 0; i < count; i++) {
+                ext = (const char *) glGetStringi(GL_EXTENSIONS, i);
+                if (glGetError() != GL_NO_ERROR)
+                    ext = "WFLINFO_GL_ERROR";
+                printf("            \"%s\"%s\n", ext, (i + 1) < count ? "," : "");
+            }
+        }
+    } else {
+        char *extensions = (char *) glGetString(GL_EXTENSIONS);
+        if (glGetError() != GL_NO_ERROR) {
+            printf("            \"WFLINFO_GL_ERROR\"");
+        } else {
+            char *splitter = strtok(extensions, " ");
+
+            // The JSON doesn't strictly need to be newline seperated, but
+            // it makes it much easier to read. Split the lines and add commas correctly
+            while(true) {
+                printf("       \"%s\"", splitter);
+                splitter = strtok(NULL, " ");
+
+                if (splitter != NULL) {
+                    printf(",\n");
+                } else {
+                    break;
+                }
+            }
+        }
+        printf("\n");
+    }
+    printf("        ]\n");
+}
+
+/// @brief Print JSON formatted OpenGL (ES) information
+static bool
+print_json(const struct options *opts)
+{
+    while(glGetError() != GL_NO_ERROR) {
+        /* Clear all errors */
+    }
+
+    const char *vendor =  get_vendor();
+    const char *renderer = get_renderer();
+    const char *version_str = get_version();
+
+    const char *platform = enum_map_to_str(platform_map, opts->platform);
+    assert(platform != NULL);
+
+    const char *api = enum_map_to_str(context_api_map, opts->context_api);
+    assert(api != NULL);
+
+    printf("{\n");
+    printf("    \"waffle\": {\n");
+    printf("        \"platform\": \"%s\",\n", platform);
+    printf("        \"api\": \"%s\"\n", api);
+    printf("    },\n");
+    printf("    \"OpenGL\": {\n");
+    printf("        \"vendor\": \"%s\",\n", vendor);
+    printf("        \"renderer\": \"%s\",\n", renderer);
+    printf("        \"version\": \"%s\"", version_str);
+    // No comma is allowed on the last element.  If this context doesn't have
+    // context flags or verbose is not requested this will be the last element.
+
+    int version = parse_version(version_str);
+
+    if (opts->context_api == WAFFLE_CONTEXT_OPENGL && version >= 31) {
+        // Add the comma and newline before the context flags.
+        printf(",\n");
+        json_print_context_flags();
+    }
+
+    // OpenGL and OpenGL ES >= 3.0 support glGetStringi(GL_EXTENSION, i).
+    const bool use_getstringi = version >= 30;
+
+    if (!glGetStringi && use_getstringi)
+        error_get_gl_symbol("glGetStringi");
+
+    if (opts->verbose) {
+        // Add the command and newline
+        printf(",\n");
+
+        // See the equivalent section in print_wflinfo() for information about
+        // this hunk
+        const char *language_str = "None";
+        if ((opts->context_api == WAFFLE_CONTEXT_OPENGL && version >= 20) ||
+                opts->context_api == WAFFLE_CONTEXT_OPENGL_ES2 ||
+                opts->context_api == WAFFLE_CONTEXT_OPENGL_ES3) {
+            language_str = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
+            if (glGetError() != GL_NO_ERROR || language_str == NULL) {
+                language_str = "WFLINFO_GL_ERROR";
+            }
+        }
+
+        printf("        \"shading language version\": \"%s\",\n", language_str);
+
+        json_print_extensions(use_getstringi);
+
+    } else {
+        // If verbose isn't being used, add a newline so that the closing curly
+        // brace will be nicely formatted
+        printf("\n");
+    }
+
+    printf("    }\n");
+    printf("}\n");
+
+    return true;
+}
+
 /// @brief Print out information about the context that was created.
 static bool
 print_wflinfo(const struct options *opts)
@@ -1141,7 +1310,12 @@ main(int argc, char **argv)
         glGetStringi = waffle_get_proc_address("glGetStringi");
     }
 
-    ok = print_wflinfo(&opts);
+    if (opts.json) {
+        ok = print_json(&opts);
+    } else {
+        ok = print_wflinfo(&opts);
+    }
+
     if (!ok)
         error_waffle();
 
-- 
2.6.4



More information about the waffle mailing list