[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