[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