[Piglit] [PATCH] egl: Add test egl-create-context-verify-gl-flavor

Ian Romanick idr at freedesktop.org
Thu Nov 8 16:59:53 PST 2012


On 11/08/2012 01:20 PM, Ian Romanick wrote:
> On 11/08/2012 10:19 AM, Chad Versace wrote:
>> This test requests various flavors (that is, api and version and
>> profile) of
>> contexts and verifies that the context's actual flavor is compatible with
>> the requested flavor.
>>
>> The following subcases fail on mesa-a196f43 with Intel Sandybridge:
>>      - For each OpenGL context >= 3.2, context creation fails with EGL
>>        error EGL_SUCCESS.
>>      - For OpenGL ES 3.0, the context version reported by glGetString is
>>        2.0.
>> All other cases skip or pass.
>
> Minor nit (with substantive comments below)... there's a lot of mixed
> tabs and spaces that make the indentation look wonkey.
>
>>
>> CC: Matt Turner <mattst88 at gmail.com>
>> CC: Iam Romanick <idr at freedesktop.org>
>> Signed-off-by: Chad Versace <chad.versace at linux.intel.com>
>> ---
>>   .../spec/egl_khr_create_context/CMakeLists.gl.txt  |   1 +
>>   .../spec/egl_khr_create_context/verify-gl-flavor.c | 408
>> +++++++++++++++++++++
>>   2 files changed, 409 insertions(+)
>>   create mode 100644
>> tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
>>
>> diff --git a/tests/egl/spec/egl_khr_create_context/CMakeLists.gl.txt
>> b/tests/egl/spec/egl_khr_create_context/CMakeLists.gl.txt
>> index 9a0c460..4063e3b 100644
>> --- a/tests/egl/spec/egl_khr_create_context/CMakeLists.gl.txt
>> +++ b/tests/egl/spec/egl_khr_create_context/CMakeLists.gl.txt
>> @@ -28,5 +28,6 @@ piglit_add_executable
>> (egl-create-context-invalid-profile invalid-profile.c comm
>>   piglit_add_executable (egl-create-context-pre-GL32-profile
>> pre-GL32-profile.c common.c)
>>   piglit_add_executable
>> (egl-create-context-valid-flag-forward-compatible-gl
>> valid-flag-forward-compatible-gl.c common.c)
>>   piglit_add_executable (egl-create-context-core-profile
>> core-profile.c common.c)
>> +piglit_add_executable (egl-create-context-verify-gl-flavor
>> verify-gl-flavor.c common.c)
>>
>>   # vim: ft=cmake:
>> diff --git a/tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
>> b/tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
>> new file mode 100644
>> index 0000000..994b209
>> --- /dev/null
>> +++ b/tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
>> @@ -0,0 +1,408 @@
>> +/* Copyright © 2012 Intel Corporation
>> + *
>> + * Permission is hereby granted, free of charge, to any person
>> obtaining a
>> + * copy of this software and associated documentation files (the
>> "Software"),
>> + * to deal in the Software without restriction, including without
>> limitation
>> + * the rights to use, copy, modify, merge, publish, distribute,
>> sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including
>> the next
>> + * paragraph) shall be included in all copies or substantial portions
>> of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
>> OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING
>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> OTHER DEALINGS
>> + * IN THE SOFTWARE.
>> + */
>> +
>> +/**
>> + * \file
>> + *
>> + * Summary
>> + * -------
>> + * Request various flavors of contexts and verify that the context's
>> actual
>> + * flavor is compatible with the requested flavor.
>> + *
>> + *
>> + * Details
>> + * --------
>> + * for each OpenGL API:
>> + *     `api` := the chosen OpenGL API
>> + *
>> + *     for each valid context version and profile of `api`:
>> + *         `flavor` := the chosen combination of version and profile
>> + *
>> + *         call eglBindAPI(`api`)
>> + *         if the binding failed:
>> + *             skip `api`
>> + *
>> + *         request a minimal EGLConfig with EGL_RENDERABLE_TYPE = `api`
>> + *         if request fails:
>> + *             skip `api`
>> + *
>> + *         request an EGLContext of `flavor`
>> + *         if request fails:
>> + *             if the EGL error is not EGL_SUCCESS:
>> + *                 `result` := skip
>> + *             else:
>> + *                 `result` := fail
>> + *
>> + *             continue to next `flavor`
>> + *
>> + *        if the context's actual flavor is compatible with the
>> requested `flavor`:
>> + *            `result` := pass
>> + *        else:
>> + *            `result` := fail
>> + *
>> + *        continue to next `flavor`
>> + */
>> +#include <ctype.h>
>> +#include <string.h>
>> +
>> +#include "piglit-util-gl-common.h"
>> +#include "piglit-util-egl.h"
>> +#include "common.h"
>> +
>> +enum gl_api {
>> +    API_GL_COMPAT,
>> +    API_GL_CORE,
>> +    API_GLES1,
>> +    API_GLES2,
>> +};
>> +
>> +static void (*piglit_glGetIntegerv)(GLenum pname, GLint *params);
>> +static const char* (*piglit_glGetString)(GLenum pname);
>> +
>> +static void
>> +fold_results(enum piglit_result *a, enum piglit_result b)
>> +{
>> +    if (*a == PIGLIT_FAIL || b == PIGLIT_FAIL)
>> +                *a = PIGLIT_FAIL;
>> +        else if (*a == PIGLIT_PASS || b == PIGLIT_PASS)
>> +                *a = PIGLIT_FAIL;
>> +        else
>> +                *a = PIGLIT_SKIP;
>> +}
>> +
>> +int
>> +get_gl_version(void)
>> +{
>> +    const char *version_string;
>> +    int scanf_count;
>> +    int major;
>> +    int minor;
>> +
>> +    version_string = (const char*) piglit_glGetString(GL_VERSION);
>
> If we don't have a test that sanity checks glGetString(GL_VERSION) vs
> glGetIntegerv(GL_MAJOR_VERION) and glGetIntegerv(GL_MINOR_VERSION),
> maybe we should do that here?  Dunno...
>
>> +
>> +    /* Skip to version number. */
>> +    while (!isdigit(*version_string) && *version_string != '\0')
>> +        version_string++;
>> +
>> +    /* Interpret version number. */
>> +    scanf_count = sscanf(version_string, "%i.%i", &major, &minor);
>> +    if (scanf_count != 2) {
>> +        printf("error: Unable to interpret GL_VERSION string: %s\n",
>> +               version_string);
>> +        piglit_report_result(PIGLIT_FAIL);
>> +        exit(1);
>> +    }
>> +
>> +    return 10 * major + minor;
>> +}
>> +
>> +static enum piglit_result
>> +check_flavor(int requested_version, enum gl_api requested_api)
>> +{
>> +    enum piglit_result result = PIGLIT_PASS;
>> +    int i;
>> +
>> +    const char *api_name = NULL;
>> +    const char *profile_name = "";
>> +
>> +    EGLint context_attribs[64];
>> +    EGLContext ctx = 0;
>> +
>> +    EGLenum requested_client_type = 0;
>> +    EGLint actual_client_type = 0;
>> +    int actual_version = 0;
>> +    GLint actual_profile = 0;
>> +
>> +    switch (requested_api) {
>> +    case API_GL_COMPAT:
>> +        requested_client_type = EGL_OPENGL_API;
>> +        api_name = "OpenGL";
>> +        if (requested_version >= 32)
>> +            profile_name = "compatibility ";
>> +        break;
>> +    case API_GL_CORE:
>> +        requested_client_type = EGL_OPENGL_API;
>> +        api_name = "OpenGL";
>> +        if (requested_version >= 32)
>> +            profile_name = "core ";
>> +        break;
>> +    case API_GLES1:
>> +    case API_GLES2:
>> +        requested_client_type = EGL_OPENGL_ES_API;
>> +        api_name = "OpenGL ES";
>> +        break;
>> +    default:
>> +        assert(0);
>> +        break;
>> +    }
>> +
>> +    printf("info: request an %s %d.%d %scontext\n",
>> +           api_name,
>> +           requested_version / 10,
>> +           requested_version % 10,
>> +           profile_name);
>> +
>> +    if (!eglBindAPI(requested_client_type)) {
>> +        /* Assume the driver doesn't support the requested API. */
>> +        result = PIGLIT_SKIP;
>> +        goto cleanup;
>> +    }
>> +
>> +    i = 0;
>> +    context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
>> +    context_attribs[i++] = requested_version / 10;
>> +    context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
>> +    context_attribs[i++] = requested_version % 10;
>> +    if (requested_api == API_GL_CORE) {
>> +        context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
>> +        context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
>> +    } else if (requested_api == API_GL_COMPAT) {
>> +        context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
>> +        context_attribs[i++] =
>> EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
>> +    }
>> +    context_attribs[i++] = EGL_NONE;
>> +
>> +    ctx = eglCreateContext(egl_dpy, cfg, EGL_NO_CONTEXT,
>> context_attribs);
>> +
>> +    if (ctx == NULL) {
>> +        printf("%s", "info: context creation failed\n");
>> +        if (eglGetError() != EGL_SUCCESS) {
>> +            result = PIGLIT_SKIP;
>> +        } else {
>> +            printf("%s", "error: eglCreateContext failed but "
>> +                   "the EGL error is EGL_SUCCESS\n");
>> +            result = PIGLIT_FAIL;
>> +        }
>> +
>> +        goto cleanup;
>> +    }
>> +
>> +    if (!piglit_check_egl_error(EGL_SUCCESS)) {
>> +        result = PIGLIT_FAIL;
>> +        goto cleanup;
>> +    }
>> +
>> +    if (!eglMakeCurrent(egl_dpy, EGL_NO_SURFACE,
>> +                        EGL_NO_SURFACE, ctx)) {
>> +        printf("%s", "error: failed to make context current\n");
>> +                goto fail;
>> +    }
>> +
>> +    if (!eglQueryContext(egl_dpy, ctx,
>> +                         EGL_CONTEXT_CLIENT_TYPE,
>> &actual_client_type)) {
>> +        printf("%s", "error: eglQueryContext(EGL_CONTEXT_CLIENT_TYPE) "
>> +               "failed\n");
>> +                goto fail;
>> +    }
>> +
>> +    if (actual_client_type != requested_client_type) {
>> +        printf("error: requested a context with
>> EGL_CONTEXT_CLIENT_TYPE=0x%x "
>> +               "but received one with EGL_CONTEXT_CLIENT_TYPE=0x%x.\n",
>> +               requested_client_type,
>> +               actual_client_type);
>> +                goto fail;
>> +    }
>> +
>> +    actual_version = get_gl_version();
>> +
>> +    if (actual_version < requested_version) {
>> +        printf("error: requested context version %d.%d but received "
>> +               "version %d.%d\n",
>> +               requested_version / 10, requested_version % 10,
>> +               actual_version / 10, actual_version % 10);
>> +                goto fail;
>> +    }
>> +
>> +    if (requested_api == API_GL_CORE ||
>> +        (requested_api == API_GL_COMPAT && requested_version >= 32)) {
>> +        piglit_glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &actual_profile);
>> +        if (!piglit_check_gl_error(GL_NO_ERROR)) {
>> +            printf("%s", "error: glGetIntegerv(GL_CONTEXT_PROFILE_MASK)"
>> +                   "failed\n");
>> +                        goto fail;
>> +        }
>> +    }
>> +
>> +    if (requested_api == API_GL_CORE) {
>> +        assert(requested_version >= 32);
>> +        if (actual_profile != EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) {
>> +            printf("error: requested an OpenGL %d.%d core context, "
>> +                   "but received a context whose profile "
>> +                   "mask is 0x%x.\n",
>> +                   requested_version / 10, requested_version % 10,
>> +                   actual_profile);
>> +                        goto fail;
>> +        }
>> +    } else if (requested_api == API_GL_COMPAT && requested_version >=
>> 32) {
>> +        if (actual_profile !=
>> EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR) {
>> +            printf("error: requested an OpenGL %d.%d compatibility
>> context, "
>> +                   "but received a context whose profile "
>> +                   "mask is 0x%x.\n",
>> +                   requested_version / 10, requested_version % 10,
>> +                   actual_profile);
>> +                        goto fail;
>> +        }
>> +    } else if (requested_api == API_GLES1) {
>> +        if (actual_version > 11) {
>> +            printf("error: requested an OpenGL ES %d.%d context, "
>> +                   "but received %d.%d context.\n",
>> +                   requested_version / 10, requested_version % 10,
>> +                   actual_version / 10, actual_version % 10);
>> +                        goto fail;
>> +        }
>> +    } else if (requested_api == API_GLES2) {
>> +        /* Nothing special to check. */
>> +    }
>> +
>> +    result = PIGLIT_PASS;
>> +        goto cleanup;
>> +
>> +fail:
>> +    result = PIGLIT_FAIL;
>> +        goto cleanup;
>> +
>> +cleanup:
>> +        /* We must unbind the context here due to a subtle
>> requirement in the
>> +         * EGL 1.4 spec published on 2011-04-06. The call to
>> eglMakeCurrent at
>> +         * the top of this function may attempt to bind a context
>> whose api
>> +         * differs from the api of the current context. Yet,
>> according to the
>> +         * EGL spec, it is illegal to bind a GL context to a surface
>> if an ES
>> +         * context is currently bound to it, and vice versa.
>> +     *
>> +         * A future revision of the EGL 1.4 spec will fix this
>> non-intuitive
>> +         * requirement.
>> +     */
>> +    if (!eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
>> +                        EGL_NO_CONTEXT)) {
>> +        printf("%s", "error: failed to unbind any current context\n");
>> +        piglit_report_result(PIGLIT_FAIL);
>> +    }
>> +
>> +    switch (result) {
>> +    case PIGLIT_PASS:
>> +        printf("%s", "result: pass\n");
>> +        break;
>> +    case PIGLIT_FAIL:
>> +        printf("%s", "result: fail\n");
>> +        break;
>> +    case PIGLIT_SKIP:
>> +        printf("%s", "result: skip\n");
>> +        break;
>> +    case PIGLIT_WARN:
>> +    default:
>> +        assert(0);
>> +        break;
>> +    }
>> +
>> +    return result;
>> +}
>> +
>> +static enum piglit_result
>> +check_opengl(void)
>> +{
>> +    enum piglit_result result = PIGLIT_SKIP;
>> +
>> +    if (!EGL_KHR_create_context_setup(EGL_OPENGL_BIT))
>> +        return PIGLIT_SKIP;
>> +
>> +    /* Try all valid OpenGL compatibility context versions. */
>> +    fold_results(&result, check_flavor(10, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(11, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(12, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(13, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(20, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(21, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(30, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(31, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(32, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(33, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(40, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(41, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(42, API_GL_COMPAT));
>> +    fold_results(&result, check_flavor(43, API_GL_COMPAT));
>> +
>> +    /* Try all valid OpenGL core context versions. */
>> +    fold_results(&result, check_flavor(32, API_GL_CORE));
>> +    fold_results(&result, check_flavor(33, API_GL_CORE));
>> +    fold_results(&result, check_flavor(40, API_GL_CORE));
>> +    fold_results(&result, check_flavor(41, API_GL_CORE));
>> +    fold_results(&result, check_flavor(42, API_GL_CORE));
>> +    fold_results(&result, check_flavor(43, API_GL_CORE));
>> +
>> +    EGL_KHR_create_context_teardown();
>> +        return result;
>> +}
>> +
>> +static enum piglit_result
>> +check_opengl_es1(void)
>> +{
>> +        enum piglit_result result = PIGLIT_SKIP;
>> +
>> +    if (!EGL_KHR_create_context_setup(EGL_OPENGL_ES_BIT))
>> +        return PIGLIT_SKIP;
>> +
>> +    /* Try all valid OpenGL ES1 context versions. */
>> +    fold_results(&result, check_flavor(10, API_GLES1));
>> +    fold_results(&result, check_flavor(11, API_GLES1));
>> +
>> +    EGL_KHR_create_context_teardown();
>> +        return result;
>> +}
>> +
>> +static enum piglit_result
>> +check_opengl_es2(void)
>> +{
>> +        enum piglit_result result = PIGLIT_SKIP;
>> +
>> +    if (!EGL_KHR_create_context_setup(EGL_OPENGL_ES2_BIT))
>> +        return PIGLIT_SKIP;
>> +
>> +    /* Try all valid context versions that are backwards-compatible
>> +         * with OpenGL ES3.
>> +         */
>> +    fold_results(&result, check_flavor(20, API_GLES2));
>> +    fold_results(&result, check_flavor(30, API_GLES2));
>> +
>> +    EGL_KHR_create_context_teardown();
>> +        return result;
>> +}
>> +
>> +int
>> +main(int argc, char **argv)
>> +{
>> +        enum piglit_result result = PIGLIT_SKIP;
>> +
>> +        /* We call glGetIntegerv with a GL context, a GLES1 context,
>> +         * and a GLES2 context current. So we shouldn't use the
>> statically
>> +         * available symbol provided by libGL. Ditto the other functions
>> +         * below.
>> +         */
>> +        piglit_glGetString = (void*) eglGetProcAddress("glGetString");
>> +        piglit_glGetIntegerv = (void*)
>> eglGetProcAddress("glGetIntegerv");
>
> Eh... what?

After our discussion on IRC, I believe that you should remove the 
GetProcAddress business, and just call the functions directly.  I can't 
conceive of an implementation where the GetProcAddress method would work 
while direct calls fail.  If such an implementation did exist, any apps 
that try to use more than one API will be in a world of hurt.

>> +
>> +        fold_results(&result, check_opengl());
>> +        fold_results(&result, check_opengl_es1());
>> +        fold_results(&result, check_opengl_es2());
>> +
>> +    piglit_report_result(result);
>> +    return EXIT_SUCCESS;
>> +}
>>
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit



More information about the Piglit mailing list