[Piglit] [PATCH v2 01/12] egl_android_native_fence_sync: Initial test for native fences.

Eric Anholt eric at anholt.net
Fri Jun 16 18:46:10 UTC 2017


Rafael Antognolli <rafael.antognolli at intel.com> writes:

> Add a test for EGL_ANDROID_native_fence_sync, and check that we can
> create a fence sync using attribute EGL_SYNC_NATIVE_FENCE_FD_ANDROID set
> to EGL_NO_NATIVE_FENCE_FD_ANDROID. Check that the several attributes are
> the correct default ones.
>
> Signed-off-by: Rafael Antognolli <rafael.antognolli at intel.com>
> ---
>  tests/egl/spec/CMakeLists.txt                      |   1 +
>  .../CMakeLists.gles2.txt                           |   9 +
>  .../egl_android_native_fence_sync/CMakeLists.txt   |   1 +
>  .../egl_android_native_fence_sync.c                | 393 +++++++++++++++++++++
>  4 files changed, 404 insertions(+)
>  create mode 100644 tests/egl/spec/egl_android_native_fence_sync/CMakeLists.gles2.txt
>  create mode 100644 tests/egl/spec/egl_android_native_fence_sync/CMakeLists.txt
>  create mode 100644 tests/egl/spec/egl_android_native_fence_sync/egl_android_native_fence_sync.c
>
> diff --git a/tests/egl/spec/CMakeLists.txt b/tests/egl/spec/CMakeLists.txt
> index d916f7a..1a66b23 100644
> --- a/tests/egl/spec/CMakeLists.txt
> +++ b/tests/egl/spec/CMakeLists.txt
> @@ -1,4 +1,5 @@
>  add_subdirectory (egl-1.4)
> +add_subdirectory (egl_android_native_fence_sync)
>  add_subdirectory (egl_ext_client_extensions)
>  add_subdirectory (egl_ext_device_query)
>  add_subdirectory (egl_ext_device_enumeration)
> diff --git a/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.gles2.txt b/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.gles2.txt
> new file mode 100644
> index 0000000..0d85ce9
> --- /dev/null
> +++ b/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.gles2.txt
> @@ -0,0 +1,9 @@
> +link_libraries(piglitutil_${piglit_target_api})
> +
> +if(PIGLIT_HAS_PTHREADS)
> +	link_libraries(${CMAKE_THREAD_LIBS_INIT})
> +endif()
> +
> +piglit_add_executable(egl_android_native_fence_sync egl_android_native_fence_sync.c)
> +
> +# vim: ft=cmake:
> diff --git a/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.txt b/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.txt
> new file mode 100644
> index 0000000..144a306
> --- /dev/null
> +++ b/tests/egl/spec/egl_android_native_fence_sync/CMakeLists.txt
> @@ -0,0 +1 @@
> +piglit_include_target_api()
> diff --git a/tests/egl/spec/egl_android_native_fence_sync/egl_android_native_fence_sync.c b/tests/egl/spec/egl_android_native_fence_sync/egl_android_native_fence_sync.c
> new file mode 100644
> index 0000000..8d8f04d
> --- /dev/null
> +++ b/tests/egl/spec/egl_android_native_fence_sync/egl_android_native_fence_sync.c
> @@ -0,0 +1,393 @@
> +/*
> + * Copyright 2016 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 Tests for EGL_ANDROID_native_fence_sync.
> + *
> + * This file attempts to exhaustively test the EGL_ANDROID_native_fence_sync
> + */
> +
> +#include <inttypes.h>
> +#include <stdarg.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +#include "piglit-util-egl.h"
> +#include "piglit-util-gl.h"
> +
> +/* Extension function pointers.
> + *
> + * Use prefix 'pegl' (piglit egl) instead of 'egl' to avoid collisions with
> + * prototypes in eglext.h. */
> +EGLSyncKHR (*peglCreateSyncKHR)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
> +EGLBoolean (*peglDestroySyncKHR)(EGLDisplay dpy, EGLSyncKHR sync);
> +EGLint (*peglClientWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
> +EGLint (*peglWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
> +EGLint (*peglDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSyncKHR sync);
> +EGLBoolean (*peglGetSyncAttribKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);

I still feel guilty that I haven't finished converting piglit to epoxy. :(

> +
> +static const EGLint canary = 0x31415926;
> +static EGLDisplay g_dpy = 0;
> +static EGLContext g_ctx = 0;
> +
> +static enum piglit_result
> +init_display(EGLenum platform, EGLDisplay *out_dpy)
> +{
> +	enum piglit_result result = PIGLIT_PASS;
> +	EGLDisplay dpy;
> +	EGLint egl_major, egl_minor;
> +	bool ok;
> +
> +	dpy = piglit_egl_get_default_display(platform);
> +	if (!dpy) {
> +		result = PIGLIT_SKIP;
> +		goto error;
> +	}
> +
> +	ok = eglInitialize(dpy, &egl_major, &egl_minor);
> +	if (!ok) {
> +		result = PIGLIT_SKIP;
> +		goto error;
> +	}
> +
> +	if (!piglit_is_egl_extension_supported(dpy, "EGL_ANDROID_native_fence_sync")) {
> +		piglit_loge("display does not support EGL_ANDROID_native_fence_sync");
> +		result = PIGLIT_SKIP;
> +		goto error;
> +
> +	}

This could just be piglit_require_egl_extension(dpy, "EGL_ANDROID_native_fence_sync")

> +
> +	*out_dpy = dpy;
> +	return result;
> +
> +error:
> +	if (dpy) {
> +		eglTerminate(dpy);
> +	}
> +	return result;
> +}
> +
> +/**
> + * Create OpenGL ES 2.0 context, make it current, and verify that it supports
> + * GL_OES_EGL_sync.
> + */
> +static enum piglit_result
> +init_context(EGLDisplay dpy, EGLContext *out_ctx)
> +{
> +	enum piglit_result result = PIGLIT_PASS;
> +	bool ok = false;
> +	EGLConfig config = 0;
> +	EGLint num_configs = 0;
> +	EGLContext ctx = 0;
> +
> +	/* Create OpenGL ES 2.0 or backwards-compatible context. */
> +	static const EGLint config_attribs[] = {
> +		EGL_RED_SIZE,		EGL_DONT_CARE,
> +		EGL_GREEN_SIZE,		EGL_DONT_CARE,
> +		EGL_BLUE_SIZE,		EGL_DONT_CARE,
> +		EGL_ALPHA_SIZE,		EGL_DONT_CARE,
> +		EGL_DEPTH_SIZE,		EGL_DONT_CARE,
> +		EGL_STENCIL_SIZE,	EGL_DONT_CARE,
> +		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT
> +				        | EGL_OPENGL_ES3_BIT_KHR,

I think having EGL_OPENGL_ES3_BIT_KHR means that you won't find a config
unless the implementation has ES3 configs.  Givne that we're only making
GLES2 contexts, can we drop that?

> +		EGL_NONE,
> +	};
> +
> +	static const EGLint context_attribs[] = {
> +		EGL_CONTEXT_CLIENT_VERSION, 2,
> +		EGL_NONE,
> +	};
> +
> +	ok = eglChooseConfig(dpy, config_attribs, &config, 1,
> +			     &num_configs);
> +	if (!ok || !config || num_configs == 0) {
> +		EGLint egl_error = eglGetError();
> +		piglit_loge("failed to get EGLConfig: %s(0x%x)",
> +			    piglit_get_egl_error_name(egl_error), egl_error);
> +		result = PIGLIT_SKIP;
> +		goto error;
> +	}
> +
> +	ok = piglit_egl_bind_api(EGL_OPENGL_ES_API);
> +	if (!ok) {
> +		piglit_loge("failed to bind EGL_OPENGL_ES_API");
> +		result = PIGLIT_FAIL;
> +		goto error;
> +
> +	}
> +
> +	ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_attribs);
> +	if (!ctx) {
> +		EGLint egl_error = eglGetError();
> +		piglit_loge("failed to create EGLContext: %s(0x%x)",
> +			    piglit_get_egl_error_name(egl_error), egl_error);
> +		result = PIGLIT_FAIL;
> +		goto error;
> +	}
> +
> +	ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx);
> +	if (!ok) {
> +		/* Skip, don't fail. Assume the context doesn't support
> +		 * GL_OES_surfaceless_context or equivalent.
> +		 */
> +		piglit_loge("failed to make context current without surface");
> +		result = PIGLIT_SKIP;
> +		goto error;
> +	}
> +
> +	piglit_dispatch_default_init(PIGLIT_DISPATCH_ES2);
> +
> +	/* From the EGL_KHR_fence_sync spec:
> +	 *
> +	 *     Each client API which supports fence commands indicates this
> +	 *     support in the form of a client API extension. If the
> +	 *     GL_OES_EGL_sync extension is supported by OpenGL ES (either
> +	 *     version 1.x or 2.0), a fence sync object may be created when the
> +	 *     currently bound API is OpenGL ES.
> +	 */
> +	if (!piglit_is_extension_supported("GL_OES_EGL_sync")) {
> +		piglit_loge("context does not support GL_OES_EGL_sync; "
> +			    "skipping test");
> +		result = PIGLIT_SKIP;
> +		goto error;
> +	}

This could just be piglit_require_extension("GL_OES_EGL_sync")

> +
> +	*out_ctx = ctx;
> +	return result;
> +
> +error:
> +	if (ctx) {
> +		eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
> +			       EGL_NO_CONTEXT);
> +		eglDestroyContext(dpy, ctx);
> +	}
> +	return result;
> +}
> +
> +/**
> + * Teardown state after each subtest completes.
> + */
> +static void
> +test_cleanup(EGLSyncKHR sync, enum piglit_result *inout_result)
> +{
> +	bool ok = false;
> +
> +	if (sync) {
> +		/* From the EGL_KHR_fence_sync spec:
> +		 *
> +		 *     If no errors are generated, EGL_TRUE is returned, and
> +		 *     <sync> will no longer be the handle of a valid sync
> +		 *     object.
> +		 */
> +		ok = peglDestroySyncKHR(g_dpy, sync);
> +		if (!ok) {
> +			piglit_loge("eglDestroySyncKHR failed");
> +			*inout_result = PIGLIT_FAIL;
> +		}
> +		if (!piglit_check_egl_error(EGL_SUCCESS)) {
> +			piglit_loge("eglDestroySyncKHR emitted an error");
> +			*inout_result = PIGLIT_FAIL;
> +		}
> +	}
> +
> +	/* Ensure that no leftover GL commands impact the next test. */
> +	if (eglGetCurrentContext()) {
> +		glFinish();
> +	}
> +
> +	if (g_dpy) {
> +		eglMakeCurrent(g_dpy, 0, 0, 0);
> +		ok = eglTerminate(g_dpy);
> +		if (!ok) {
> +			piglit_loge("failed to terminate EGLDisplay");
> +			*inout_result = PIGLIT_FAIL;
> +		}
> +	}
> +
> +	g_dpy = EGL_NO_DISPLAY;
> +	g_ctx = EGL_NO_CONTEXT;
> +}
> +
> +/**
> + * Setup state before each subtest begins.
> + */
> +static enum piglit_result
> +test_setup(void)
> +{
> +	enum piglit_result result = PIGLIT_PASS;
> +
> +	/* Just in case the previous test forgot to unset these pointers... */
> +	g_dpy = EGL_NO_DISPLAY;
> +	g_ctx = EGL_NO_CONTEXT;
> +
> +	result = init_display(EGL_NONE, &g_dpy);
> +	if (result != PIGLIT_PASS) {
> +		goto cleanup;
> +	}
> +

stray \n

> +
> +	result = init_context(g_dpy, &g_ctx);
> +	if (result != PIGLIT_PASS) {
> +		goto cleanup;
> +	}

I think common style is for single-line blocks to not have {} around
them.  I don't think it's important to change for the patches to land.

> +	/* Ensure that a context is bound so that the test can create syncs. */
> +	eglMakeCurrent(g_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, g_ctx);
> +
> +cleanup:
> +	if (result != PIGLIT_PASS) {
> +		test_cleanup(EGL_NO_SYNC_KHR, &result);
> +	}
> +	return result;
> +}
> +
> +static enum piglit_result
> +test_eglCreateSyncKHR_native_default_attributes(void *test_data)
> +{
> +	enum piglit_result result = PIGLIT_PASS;
> +	EGLSyncKHR sync = 0;
> +	EGLint sync_type = canary,
> +	       sync_status = canary,
> +	       sync_condition = canary;
> +	bool ok = false;
> +
> +	result = test_setup();
> +	if (result != PIGLIT_PASS) {
> +		return result;
> +	}
> +
> +	sync = peglCreateSyncKHR(g_dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
> +	if (sync == EGL_NO_SYNC_KHR) {
> +		piglit_loge("eglCreateSyncKHR(EGL_SYNC_NATIVE_FENCE_ANDROID) failed");
> +		result = PIGLIT_FAIL;
> +		goto cleanup;
> +	}
> +
> +	ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_TYPE_KHR, &sync_type);
> +	if (!ok) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) failed");
> +		result = PIGLIT_FAIL;
> +	}
> +	if (!piglit_check_egl_error(EGL_SUCCESS)) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) emitted "
> +			    "an error");
> +		result = PIGLIT_FAIL;
> +	}

I'd be tempted to fold those checks to "if (!ok ||
!piglit_check_egl_error(EGL_SUCCESS)) {"

Either way, though.

> +	if (sync_type != EGL_SYNC_NATIVE_FENCE_ANDROID) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_TYPE_KHR) returned "
> +			    "0x%x but expected EGL_SYNC_NATIVE_FENCE_ANDROID(0x%x)",
> +			    sync_type, EGL_SYNC_NATIVE_FENCE_ANDROID);
> +		result = PIGLIT_FAIL;
> +	}
> +
> +	ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_STATUS_KHR, &sync_status);
> +	if (!ok) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) failed");
> +		result = PIGLIT_FAIL;
> +	}
> +	if (!piglit_check_egl_error(EGL_SUCCESS)) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_STATUS_KHR) emitted "
> +			    "an error");
> +		result = PIGLIT_FAIL;
> +	}
> +
> +	ok = peglGetSyncAttribKHR(g_dpy, sync, EGL_SYNC_CONDITION_KHR, &sync_condition);
> +	if (!ok) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) failed");
> +		result = PIGLIT_FAIL;
> +	}
> +	if (!piglit_check_egl_error(EGL_SUCCESS)) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) "
> +			    "emitted an error");
> +		result = PIGLIT_FAIL;
> +	}
> +	if (sync_condition != EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR) {
> +		piglit_loge("eglGetSyncAttribKHR(EGL_SYNC_CONDITION_KHR) "
> +			    "returned 0x%x but expected "
> +			    "EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR(0x%x)",
> +			    sync_condition, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR);
> +		result = PIGLIT_FAIL;
> +	}
> +
> +cleanup:
> +	test_cleanup(sync, &result);
> +	return result;
> +}
> +
> +static enum piglit_result
> +test_eglCreateSyncKHR_native_from_fd(void *test_data)
> +{
> +	return PIGLIT_PASS;
> +}
> +
> +static const struct piglit_subtest fence_sync_subtests[] = {
> +	{
> +		"eglCreateSyncKHR_native_no_fence",
> +		"eglCreateSyncKHR_native_no_fence",
> +		test_eglCreateSyncKHR_native_default_attributes,
> +	},
> +	{
> +		"eglCreateSyncKHR_native_from_fd",
> +		"eglCreateSyncKHR_native_from_fd",
> +		test_eglCreateSyncKHR_native_from_fd,
> +	},
> +	{0},

The native_from_fd test should probably be added in the next patch, not
this one.

> +};
> +
> +static void
> +init_egl_extension_funcs(void)
> +{
> +	peglCreateSyncKHR = (void*) eglGetProcAddress("eglCreateSyncKHR");
> +	peglDestroySyncKHR = (void*) eglGetProcAddress("eglDestroySyncKHR");
> +	peglClientWaitSyncKHR = (void*) eglGetProcAddress("eglClientWaitSyncKHR");
> +	peglWaitSyncKHR = (void*) eglGetProcAddress("eglWaitSyncKHR");
> +	peglDupNativeFenceFDANDROID = (void*) eglGetProcAddress("eglDupNativeFenceFDANDROID");
> +	peglGetSyncAttribKHR = (void*) eglGetProcAddress("eglGetSyncAttribKHR");
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> +	enum piglit_result result = PIGLIT_SKIP;
> +	const char **selected_subtests = NULL;
> +	size_t num_selected_subtests = 0;
> +	const struct piglit_subtest *subtests = fence_sync_subtests;
> +
> +	/* Strip common piglit args. */
> +	piglit_strip_arg(&argc, argv, "-fbo");
> +	piglit_strip_arg(&argc, argv, "-auto");
> +
> +	piglit_parse_subtest_args(&argc, argv, subtests, &selected_subtests,
> +				  &num_selected_subtests);
> +
> +	if (argc > 1) {
> +		fprintf(stderr, "usage error\n");
> +		piglit_report_result(PIGLIT_FAIL);
> +	}
> +
> +	init_egl_extension_funcs();
> +	result = piglit_run_selected_subtests(subtests, selected_subtests,
> +					      num_selected_subtests, result);
> +	piglit_report_result(result);
> +	assert(!"unreachable");
> +	return EXIT_FAILURE;
> +}

With the ES3 and native_from_fd changes, and then whatever of the other
cleanups you feel like,

Reviewed-by: Eric Anholt <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/piglit/attachments/20170616/980c9f0b/attachment.sig>


More information about the Piglit mailing list