[waffle] [RFC 3/3] wflinfo.c: Add a --json flag that prints json

Frank Henigman fjhenigman at google.com
Sun Dec 27 07:49:32 PST 2015


On Wed, Dec 16, 2015 at 8:37 PM,  <baker.dylan.c at gmail.com> wrote:
> 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>
> ---
>  src/utils/wflinfo.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 173 insertions(+), 1 deletion(-)
>
> diff --git a/src/utils/wflinfo.c b/src/utils/wflinfo.c
> index b843757..154cf3c 100644
> --- a/src/utils/wflinfo.c
> +++ b/src/utils/wflinfo.c
> @@ -83,6 +83,9 @@ static const char *usage_message =
>      "    --debug-context\n"
>      "        Create a debug context.\n"
>      "\n"
> +    "    --json\n"
> +    "        Print a JSON formatted summary.\n"
> +    "\n"

I would like -j to work too.

>      "    -h, --help\n"
>      "        Print wflinfo usage information.\n"
>      "\n"
> @@ -102,6 +105,7 @@ enum {
>      OPT_VERBOSE = 'v',
>      OPT_DEBUG_CONTEXT,
>      OPT_FORWARD_COMPATIBLE,
> +    OPT_JSON,
>      OPT_HELP = 'h',
>  };
>
> @@ -113,6 +117,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 },
>  };
> @@ -250,6 +255,8 @@ struct options {
>
>      bool verbose;
>
> +    bool json;
> +
>      bool context_forward_compatible;
>      bool context_debug;
>
> @@ -393,6 +400,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;
> @@ -564,6 +574,163 @@ print_context_flags(void)
>      return;
>  }
>
> +static void
> +json_print_context_flags(void)
> +{
> +    int flag_count = sizeof(flags) / sizeof(flags[0]);
> +    GLint context_flags = 0;
> +
> +    printf("    \"context flags\": ");
> +
> +    glGetIntegerv(GL_CONTEXT_FLAGS, &context_flags);
> +    if (glGetError() != GL_NO_ERROR) {
> +        printf("\"WFLINFO_GL_ERROR\"\n");
> +        return;
> +    }
> +
> +    if (context_flags == 0) {
> +        printf("\"0x0\"\n");
> +        return;
> +    }
> +
> +    printf("[\n");
> +    for (int i = 0; i < flag_count; i++) {
> +        if ((flags[i].flag & context_flags) != 0) {
> +            printf("        \"%s\"", flags[i].str);
> +            context_flags = context_flags & ~flags[i].flag;
> +            if (i != flag_count) {
> +                printf(",\n");
> +            }
> +        }
> +    }
> +    for (int i = 0; context_flags != 0; context_flags >>= 1, i++) {
> +        if ((context_flags & 1) != 0) {
> +            printf(",\n");
> +            printf("        0x%x", 1 << i);
> +        }
> +    }
> +    printf("    ]");
> +
> +    return;
> +}
> +
> +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("    \"platform\": \"%s\",\n", platform);
> +    printf("    \"api\": \"%s\",\n", api);
> +    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");
> +
> +    return true;
> +}
> +

I think some key strings should be a bit more specific or nested, like
"opengl version:" or "opengl : { version :" instead of just "version"
in case we expand some day to include things like egl version.

Perhaps this could be refactored to cut down on duplication between
the json parts and their original non-json counterparts.

It would be nice to see the structure of the json more clearly,
perhaps one long string with the values substituted in, though that's
a bit less convenient in C as compared to say python.

>  /// @brief Print out information about the context that was created.
>  static bool
>  print_wflinfo(const struct options *opts)
> @@ -1144,7 +1311,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
>
> _______________________________________________
> waffle mailing list
> waffle at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/waffle


More information about the waffle mailing list