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

Dylan Baker baker.dylan.c at gmail.com
Wed Jan 6 15:03:00 PST 2016


On Wed, Jan 6, 2016 at 2:06 PM, Emil Velikov <emil.l.velikov at gmail.com>
wrote:

> Hi Dylan,
>
> Perhaps I'm not the best person to comment on the JSON side of things
> (esp since Frank sent related series a few hours ago), then again a
> few things, that might be interesting.
>
> On 5 January 2016 at 19:46,  <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>
> >
> > 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);
> const unsigned flag_count ?
>
> > +    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("[]");
> Missing \n ?
>
>
Nope, gets covered later. This is a little odd to look at because that \n
gets added later, because of the comma/no-comma madness that JSON enforces.


> > +        return;
> > +    }
> > +
> > +    printf("[\n");
> > +    for (int i = 0; i < flag_count; i++) {
> unsigned 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) {
> This always evaluates to true, doesn't it ?
>

Doesn't it evaluate to true in every case but the last iteration?


>
> > +                printf(",\n");
> > +            }
> > +        }
> > +    }
> > +    for (int i = 0; gl_context_flags != 0; gl_context_flags >>= 1, i++)
> {
> > +        if ((gl_context_flags & 1) != 0) {
> > +            printf(",\n");
> We'll get two consecutive ",\n" considering the one above ?
>

nope, because you don't get ",\n" in the last iteration of the above loop.


>
> > +            printf("        0x%x", 1 << i);
> ... and we're missing the \n for the last entry.
>
> Easier way might be to do "leading" \n's ?
>
> > +        }
> > +    }
> > +    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\"");
> Intentional difference in tabulation between previous function, here
> and else statement ?
>

nope, I'll fix that.


>
> > +        } 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, " ");
> > +
> Note to self: do we care if a driver returns a single extension
> (and/or empty extensions string) ?
>
> > +            // 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 */
> Space between while and (... then again why the while loop ?
>

> > +    }
> > +
> > +    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) {
> Align the last two ones - o (in opts) should be the same column as the (
>

that looks like a readability nightmare:

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";
     }
}


>
> > +            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;
> Afaict you can make the function return void ?
>
> Seems that most (all?) of the comments here apply to the existing code
> in wflinfo.c where this was inspired/copied from. As mentioned by
> others - pondering on reusing the existing functions... I'll give it a
> quick test tomorrow.
>
> A bit tired so do take my comments with a grain of salt.
>
> That said (with or without the suggestions in 1 and 3) patches 1-3 are
> Reviewed-by: Emil Velikov <emil.velikov at collabora.com>
>
> -Emil
>

I'll talk to Frank, but I think his series covers everything mine set out
to do, if does, I'll just withdraw mine.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/waffle/attachments/20160106/d46efeee/attachment-0001.html>


More information about the waffle mailing list