[Piglit] [PATCH 2/2] egl: Add test egl-create-context-verify-gl-flavor (v2)

Chad Versace chad.versace at linux.intel.com
Fri Nov 9 11:45:47 PST 2012


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;
+	}
+
+	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");
+
+	fold_results(&result, check_opengl());
+	fold_results(&result, check_opengl_es1());
+	fold_results(&result, check_opengl_es2());
+
+	piglit_report_result(result);
+	return EXIT_SUCCESS;
+}
-- 
1.7.11.7



More information about the Piglit mailing list