[Piglit] [PATCH 2/2] egl: Add test egl-create-context-verify-gl-flavor (v2)
Ian Romanick
idr at freedesktop.org
Tue Nov 13 16:36:57 PST 2012
On 11/09/2012 11:45 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.
>
> v2:
> - Document that we use eglGetProcAddress to avoid piglit-dispatch.
> - Also verify that glGetString(GL_VERSION) and
> glGetIntgerv(GL_MAJOR/MINOR_VERSION) return the same version.
>
> 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>
> ---
>
> Ian, I see your point in the foolishness of using eglGetProcAddress for the
> core functions. I tried your suggestion and attempted to use the statically
> available glGetIntegerv in this test, but got a surprise from piglit-dispatch.
>
> So, I still insist that we should use eglGetProcAddress in this test, but now
> for a different reason. See the comments in main().
>
>
> tests/all_egl.tests | 1 +
> .../spec/egl_khr_create_context/CMakeLists.gl.txt | 1 +
> .../spec/egl_khr_create_context/verify-gl-flavor.c | 443 +++++++++++++++++++++
> 3 files changed, 445 insertions(+)
> create mode 100644 tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
>
> diff --git a/tests/all_egl.tests b/tests/all_egl.tests
> index ab04191..56cdf6e 100644
> --- a/tests/all_egl.tests
> +++ b/tests/all_egl.tests
> @@ -42,3 +42,4 @@ create_context['valid forward-compatible flag GL'] = concurrent_test('egl-create
> create_context['invalid profile'] = concurrent_test('egl-create-context-invalid-profile')
> create_context['3.2 core profile required'] = concurrent_test('egl-create-context-core-profile')
> create_context['pre-GL3.2 profile'] = concurrent_test('egl-create-context-pre-GL32-profile')
> +create_context['verify GL flavor'] = concurrent_test('egl-create-context-verify-gl-flavor')
> 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..c231b4a
> --- /dev/null
> +++ b/tests/egl/spec/egl_khr_create_context/verify-gl-flavor.c
> @@ -0,0 +1,443 @@
> +/* 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 (*my_glGetIntegerv)(GLenum pname, GLint *params);
> +static const char* (*my_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*) my_glGetString(GL_VERSION);
> +
> + /* 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);
> + }
> +
> + if (major >= 3) {
> + /* Verify the glGetIntegerv returns the same version as
> + * glGetString.
> + */
> +
> + int major2;
> + int minor2;
> +
> + my_glGetIntegerv(GL_MAJOR_VERSION, &major2);
> + my_glGetIntegerv(GL_MINOR_VERSION, &minor2);
> +
> + if (major != major2 || minor != minor2) {
> + printf("error: glGetString reports version %d.%d "
> + "but glGetIntegerv reports version %d.%d.\n",
> + major, minor,
> + major2, minor2);
> + piglit_report_result(PIGLIT_FAIL);
> + }
> + }
> +
> + return 10 * major + minor;
> +}
> +
> +static enum piglit_result
> +check_flavor(int requested_version, enum gl_api requested_api)
> +{
> + static bool is_dispatch_init = false;
> +
> + 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;
> + }
I missed this before. This usage requires EGL_KHR_surfaceless_context.
At this point, I think it's fine to require that extension. If
someone wants to run this test on an implementation that doesn't support
it, we will welcome patches from them.
> +
> + if (!is_dispatch_init) {
> + /* We must postpone initialization of piglit-dispatch until
> + * a context is current.
> + */
> + piglit_dispatch_default_init();
> + is_dispatch_init = true;
> + }
> +
> + 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)) {
> + my_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", "info: pass\n");
> + break;
> + case PIGLIT_FAIL:
> + printf("%s", "info: fail\n");
> + break;
> + case PIGLIT_SKIP:
> + printf("%s", "info: 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;
> +
> + /* This test doesn't use the glGetString symbol because using
> + * piglit-dispatch introduces difficulties with this test. Instead we
> + * choose to bypass it with eglGetProcAddress.
> + *
> + * Don't be fooled. The symbol glGetString is not the glGetString
> + * declared in <GL/gl.h> and exposed statically from libGL. It is
> + * instead a function pointer defined by piglit-dispatch that is
> + * resolved by glXGetProcAddress.
> + */
> + my_glGetString = (void*) eglGetProcAddress("glGetString");
> + my_glGetIntegerv = (void*) eglGetProcAddress("glGetIntegerv");
At some point I'd like to understand why that is, but this code change
is fine for now.
> +
> + fold_results(&result, check_opengl());
> + fold_results(&result, check_opengl_es1());
> + fold_results(&result, check_opengl_es2());
> +
> + piglit_report_result(result);
> + return EXIT_SUCCESS;
> +}
>
More information about the Piglit
mailing list