[Piglit] [PATCH v3 2/2] EGL_CHROMIUM_sync_control: Add initial tests.

Sarah Sharp sarah.a.sharp at linux.intel.com
Tue May 6 12:10:59 PDT 2014


Test the EGL_CHROMIUM_sync_control extension, which is similar to
the GLX_OML_sync_control extension:

http://www.opengl.org/registry/specs/OML/glx_sync_control.txt

The extension only defines one new function,
EGL_CHROMIUM_get_sync_values, which is equivalent to the
glXGetSyncValuesOML function.

It's difficult to test the Media Stream Counter (MSC) without the
equivalent function to get the MSC rate (glXGetMscRateOML).  The test at
least makes sure MSC and SBC increment after two SwapBuffers() calls.
UST is system-dependent, so it may behave differently on Windows, Linux,
and Apple.  The test just makes sure it increments monotonically.

The test uses Chad's new subtest infrastructure and the EGL convenience
functions from egl-util.c.

Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
Cc: Chad Versace <chad.versace at linux.intel.com>
Cc: Rob Bradford <rob at linux.intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp at linux.intel.com>
---

v2:
 - Remove glFinish in egl_util_run.  Tests still pass without it.
 - Fix memory leak of vinfo in create_window.
 - Make error handling code in egl_util_run more readable/verifiable.
 - Make sure test is const in egl_util_run.
 - The extension *name* should be EGL_CHROMIUM_sync_control, and the new
   *function* is called EGL_CHROMIUM_get_sync_values.
v3:
 - rename all files to refer to the extension name,
   EGL_CHROMIUM_sync_control.
 - Check what the minimum swap buffers interval is for the EGL
   configuration.  If it's non-zero, calling SwapBuffers() twice ensures
   that at least one vertical retrace will occur, and MSC will increment.
 - Don't fail the MSC test if the minimum swap buffers interval is zero.
 - Use nanosleep instead of sleep in the UST test.  Sleep for two
   vertical retraces (0.032 seconds).  UST is system-dependent, but it
   doesn't make sense for someone to define UST units to be less than a
   vertical retrace at 30Hz refresh rate.

 tests/all.py                                       |   4 +
 tests/egl/spec/CMakeLists.txt                      |   1 +
 .../egl_chromium_sync_control/CMakeLists.gles2.txt |   7 +
 .../spec/egl_chromium_sync_control/CMakeLists.txt  |   1 +
 .../egl_chromium_sync_control.c                    | 291 +++++++++++++++++++++
 5 files changed, 304 insertions(+)
 create mode 100644 tests/egl/spec/egl_chromium_sync_control/CMakeLists.gles2.txt
 create mode 100644 tests/egl/spec/egl_chromium_sync_control/CMakeLists.txt
 create mode 100644 tests/egl/spec/egl_chromium_sync_control/egl_chromium_sync_control.c

diff --git a/tests/all.py b/tests/all.py
index a67e725..607223b 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -3844,6 +3844,10 @@ egl_khr_fence_sync = {}
 spec['EGL_KHR_fence_sync'] = egl_khr_fence_sync
 egl_khr_fence_sync['conformance'] = concurrent_test('egl_khr_fence_sync')
 
+egl_chromium_sync_control = {}
+spec['EGL_CHROMIUM_sync_control'] = egl_chromium_sync_control
+egl_chromium_sync_control['conformance'] = concurrent_test('egl_chromium_sync_control')
+
 gles20 = {}
 spec['!OpenGL ES 2.0'] = gles20
 gles20['glsl-fs-pointcoord'] = concurrent_test('glsl-fs-pointcoord_gles2')
diff --git a/tests/egl/spec/CMakeLists.txt b/tests/egl/spec/CMakeLists.txt
index 84c3fa0..a5e749f 100644
--- a/tests/egl/spec/CMakeLists.txt
+++ b/tests/egl/spec/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory (egl-1.4)
 add_subdirectory (egl_ext_client_extensions)
 add_subdirectory (egl_khr_create_context)
 add_subdirectory (egl_khr_fence_sync)
+add_subdirectory (egl_chromium_sync_control)
diff --git a/tests/egl/spec/egl_chromium_sync_control/CMakeLists.gles2.txt b/tests/egl/spec/egl_chromium_sync_control/CMakeLists.gles2.txt
new file mode 100644
index 0000000..d0f1881
--- /dev/null
+++ b/tests/egl/spec/egl_chromium_sync_control/CMakeLists.gles2.txt
@@ -0,0 +1,7 @@
+link_libraries(
+	piglitutil_${piglit_target_api}
+)
+
+piglit_add_executable(egl_chromium_sync_control ../../egl-util.c egl_chromium_sync_control.c)
+
+# vim: ft=cmake:
diff --git a/tests/egl/spec/egl_chromium_sync_control/CMakeLists.txt b/tests/egl/spec/egl_chromium_sync_control/CMakeLists.txt
new file mode 100644
index 0000000..144a306
--- /dev/null
+++ b/tests/egl/spec/egl_chromium_sync_control/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/egl/spec/egl_chromium_sync_control/egl_chromium_sync_control.c b/tests/egl/spec/egl_chromium_sync_control/egl_chromium_sync_control.c
new file mode 100644
index 0000000..9daf0f9
--- /dev/null
+++ b/tests/egl/spec/egl_chromium_sync_control/egl_chromium_sync_control.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2014 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_CHROMIUM_sync_control.
+ *
+ * This file tests the unregistered ChromeOS-specific EGL extension
+ * EGL_CHROMIUM_sync_control.  The extension is similar to the GLX
+ * OML_sync_control extension, but only implements the glXGetSyncValuesOML
+ * function, renaming it eglGetSyncValuesCHROMIUM.  This tests that function.
+ */
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "piglit-util-egl.h"
+#include "piglit-util-gl-common.h"
+#include "../../egl-util.h"
+
+/* Piglit extension function pointer. */
+EGLBoolean (*peglGetSyncValuesCHROMIUM)(EGLDisplay display, EGLSurface surface, EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
+
+static const struct piglit_subtest subtests[];
+
+static const EGLuint64KHR canary = 0xdecafc0ffee;
+const char *extensions[] = { "EGL_CHROMIUM_sync_control", NULL };
+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_NONE,
+};
+
+
+static char *program_name;
+
+static enum piglit_result
+test_eglGetSyncValuesCHROMIUM_null_pointers(struct egl_state *state)
+{
+	EGLuint64KHR counter;
+
+	/* Note: it would be fun to get trinity fuzzing Mesa calls. */
+	if (peglGetSyncValuesCHROMIUM(NULL, state->surf, &counter, &counter, &counter)) {
+		piglit_loge("eglGetSyncValuesCHROMIUM succeeded with NULL display");
+		return PIGLIT_FAIL;
+	}
+	if (peglGetSyncValuesCHROMIUM(state->egl_dpy, NULL, &counter, &counter, &counter)) {
+		piglit_loge("eglGetSyncValuesCHROMIUM succeeded with NULL surface");
+		return PIGLIT_FAIL;
+	}
+	if (peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, NULL, &counter, &counter)) {
+		piglit_loge("eglGetSyncValuesCHROMIUM succeeded with NULL ust pointer");
+		return PIGLIT_FAIL;
+	}
+	if (peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, &counter, NULL, &counter)) {
+		piglit_loge("eglGetSyncValuesCHROMIUM succeeded with NULL msc pointer");
+		return PIGLIT_FAIL;
+	}
+	if (peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, &counter, &counter, NULL)) {
+		piglit_loge("eglGetSyncValuesCHROMIUM succeeded with NULL sbc pointer");
+		return PIGLIT_FAIL;
+	}
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+get_ust_values(struct egl_state *state, EGLuint64KHR *ust,
+		EGLuint64KHR *ust2, EGLuint64KHR *ust3)
+{
+	EGLuint64KHR msc = canary;
+	EGLuint64KHR sbc = canary;
+	struct timespec sleep_time;
+
+	/* Sleep for 0.032 seconds, which is at least two vertical retraces at 30 Hz. */
+	sleep_time.tv_sec = 0;
+	sleep_time.tv_nsec = 32*1000*1000;
+
+	if (!peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, ust, &msc, &sbc)) {
+		piglit_loge("Unexpected failure on first UST fetch");
+		return PIGLIT_FAIL;
+	}
+	nanosleep(&sleep_time, NULL);
+	if (!peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, ust2, &msc, &sbc)) {
+		piglit_loge("Unexpected failure on second UST fetch");
+		return PIGLIT_FAIL;
+	}
+	nanosleep(&sleep_time, NULL);
+	if (!peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf, ust3, &msc, &sbc)) {
+		piglit_loge("Unexpected failure on third UST fetch");
+		return PIGLIT_FAIL;
+	}
+	return PIGLIT_PASS;
+}
+
+/**
+ * Verify the UST counter functionality.  From the OML_sync_control spec:
+ *
+ * The Unadjusted System Time (or UST) is a 64-bit monotonically increasing
+ * counter that is available throughout the system. UST is not a resource that
+ * is controlled by OpenGL, so it is not defined further as part of this
+ * extension.
+ */
+static enum piglit_result
+test_eglGetSyncValuesCHROMIUM_ust_test(struct egl_state *state)
+{
+	EGLuint64KHR ust = canary;
+	EGLuint64KHR ust2 = canary;
+	EGLuint64KHR ust3 = canary;
+
+	if (get_ust_values(state, &ust, &ust2, &ust3) != PIGLIT_PASS)
+		return PIGLIT_FAIL;
+
+	if (ust > ust2 || ust > ust3 || ust2 > ust3) {
+		piglit_loge("eglGetSyncValuesCHROMIUM UST is not monotonically increasing");
+		piglit_loge("UST values 0.032 seconds apart: %lu %lu %lu",
+				ust, ust2, ust3);
+		return PIGLIT_FAIL;
+	}
+
+	return PIGLIT_PASS;
+}
+
+/**
+ * Verify the SBC and MSC counter functionality. From the OML_sync_control spec:
+ *
+ * The graphics Media Stream Counter (or graphics MSC) is a counter that is
+ * unique to the graphics subsystem and increments for each vertical retrace
+ * that occurs.
+ *
+ * The Swap Buffer Counter (SBC) is an attribute of a GLXDrawable and is
+ * incremented each time a swap buffer action is performed on the associated
+ * drawable.
+ *
+ *
+ * Calling glFinish() won't force the swap buffers to happen; it will only flush
+ * the command to the compositor.  By default, the buffer swap for each drawable
+ * object is rate limited to happen no more than 60 times a second.
+ * SwapBuffers() will block in order to enforce this.  Therefore, by the time
+ * our second SwapBuffer() call returns, we are guaranteed that SBC will have
+ * incremented at least once, possibly twice, but not more than twice.
+ *
+ * When buffer swaps are synchronized to the vertical retrace (which is the
+ * case when the surface's swap interval is non-zero), then the MSC increments
+ * at least as frequently as SBC, and maybe more frequently.
+ */
+static enum piglit_result
+test_eglGetSyncValuesCHROMIUM_msc_and_sbc_test(struct egl_state *state)
+{
+	EGLuint64KHR ust = canary;
+	EGLuint64KHR msc = canary;
+	EGLuint64KHR sbc = canary;
+	EGLuint64KHR ust2 = canary;
+	EGLuint64KHR msc2 = canary;
+	EGLuint64KHR sbc2 = canary;
+	EGLint min_swap_interval;
+
+	if (!eglGetConfigAttrib(state->egl_dpy, state->cfg,
+				EGL_MIN_SWAP_INTERVAL, &min_swap_interval)) {
+		piglit_loge("Could not get swap interval config attrib");
+		return PIGLIT_FAIL;
+	}
+	if (!peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf,
+				&ust, &msc, &sbc)) {
+		piglit_loge("Unexpected failure on first sbc fetch");
+		return PIGLIT_FAIL;
+	}
+
+	glClearColor(0.0, 1.0, 0.0, 1.0);
+	glClear(GL_COLOR_BUFFER_BIT);
+	eglSwapBuffers(state->egl_dpy, state->surf);
+
+	glClearColor(1.0, 0.0, 0.0, 1.0);
+	glClear(GL_COLOR_BUFFER_BIT);
+	eglSwapBuffers(state->egl_dpy, state->surf);
+
+	if (!peglGetSyncValuesCHROMIUM(state->egl_dpy, state->surf,
+				&ust2, &msc2, &sbc2)) {
+		piglit_loge("Unexpected failure on second sbc fetch");
+		return PIGLIT_FAIL;
+	}
+	if (sbc2 == sbc) {
+		piglit_loge("SBC did not change after second SwapBuffers: %lu", sbc);
+		return PIGLIT_FAIL;
+	}
+	if (min_swap_interval > 0 && msc == msc2) {
+		piglit_loge("MSC did not change after second SwapBuffers: %lu", msc);
+		return PIGLIT_FAIL;
+	}
+	if (sbc2 > (sbc + 2)) {
+		piglit_loge("SBC increased by more than two after second SwapBuffers: %lu (before) %lu (after)", sbc, sbc2);
+		return PIGLIT_FAIL;
+	}
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+run_test(enum piglit_result (*test_func)(struct egl_state *state))
+{
+	struct egl_test test;
+
+	egl_init_test(&test);
+	test.extensions = extensions;
+	test.config_attribs = config_attribs;
+	test.draw = test_func;
+	test.stop_on_failure = false;
+	return egl_util_run(&test, 1, &program_name);
+}
+
+static enum piglit_result
+init_eglGetSyncValuesCHROMIUM_null_pointers(void *test_data)
+{
+	return run_test(test_eglGetSyncValuesCHROMIUM_null_pointers);
+}
+
+static enum piglit_result
+init_eglGetSyncValuesCHROMIUM_ust_test(void *test_data)
+{
+	return run_test(test_eglGetSyncValuesCHROMIUM_ust_test);
+}
+
+static enum piglit_result
+init_eglGetSyncValuesCHROMIUM_msc_and_sbc_test(void *test_data)
+{
+	return run_test(test_eglGetSyncValuesCHROMIUM_msc_and_sbc_test);
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"eglGetSyncValuesCHROMIUM_null_pointers",
+		"eglGetSyncValuesCHROMIUM_null_pointers",
+		init_eglGetSyncValuesCHROMIUM_null_pointers,
+	},
+	{
+		"eglGetSyncValuesCHROMIUM_ust_test",
+		"eglGetSyncValuesCHROMIUM_ust_test",
+		init_eglGetSyncValuesCHROMIUM_ust_test,
+	},
+	{
+		"eglGetSyncValuesCHROMIUM_msc_and_sbc_test",
+		"eglGetSyncValuesCHROMIUM_msc_and_sbc_test",
+		init_eglGetSyncValuesCHROMIUM_msc_and_sbc_test,
+	},
+	{0},
+};
+
+int
+main(int argc, char **argv)
+{
+	const char **selected_subtests = NULL;
+	enum piglit_result result = PIGLIT_SKIP;
+	size_t num_selected_subtests = 0;
+
+	program_name = basename(argv[0]);
+	piglit_automatic = GL_TRUE;
+	piglit_parse_subtest_args(&argc, argv, subtests, &selected_subtests,
+			          &num_selected_subtests);
+
+	peglGetSyncValuesCHROMIUM = (void*) eglGetProcAddress("eglGetSyncValuesCHROMIUM");
+	result = piglit_run_selected_subtests(subtests, selected_subtests,
+					      num_selected_subtests, result);
+	piglit_report_result(result);
+	assert(!"unreachable");
+	return EXIT_FAILURE;
+}
-- 
1.8.3.2



More information about the Piglit mailing list