diff --git a/configure.ac b/configure.ac index 86940d5d..8baef885 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,7 @@ AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes) if test x$enable_egl = xyes; then AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support]) PKG_CHECK_MODULES(EGL, [egl >= 7.10 glesv2]) + PKG_CHECK_MODULES([EGL_TESTS], [egl >= 7.10 glesv2 wayland-client wayland-egl]) fi AC_ARG_ENABLE(xkbcommon, diff --git a/protocol/wayland-test.xml b/protocol/wayland-test.xml index 2993f087..18b66253 100644 --- a/protocol/wayland-test.xml +++ b/protocol/wayland-test.xml @@ -51,5 +51,12 @@ + + + + + + diff --git a/tests/Makefile.am b/tests/Makefile.am index 42788cbf..baf8b7cf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -17,6 +17,11 @@ weston_tests = \ subsurface.weston \ $(xwayland_test) +if ENABLE_EGL +weston_tests += \ + buffer-count.weston +endif + AM_TESTS_ENVIRONMENT = \ abs_builddir='$(abs_builddir)'; export abs_builddir; @@ -63,6 +68,10 @@ weston_test_la_SOURCES = \ wayland-test-protocol.c \ wayland-test-server-protocol.h +if ENABLE_EGL +weston_test_la_LDFLAGS += $(EGL_TESTS_LIBS) +endif + libtest_runner_la_SOURCES = \ weston-test-runner.c \ weston-test-runner.h @@ -111,6 +120,9 @@ text_weston_LDADD = libtest-client.la subsurface_weston_SOURCES = subsurface-test.c subsurface_weston_LDADD = libtest-client.la +buffer_count_weston_SOURCES = buffer-count-test.c +buffer_count_weston_LDADD = libtest-client.la $(EGL_TESTS_LIBS) + xwayland_weston_SOURCES = xwayland-test.c xwayland_weston_CFLAGS = $(GCC_CFLAGS) $(XWAYLAND_TEST_CFLAGS) xwayland_weston_LDADD = libtest-client.la $(XWAYLAND_TEST_LIBS) diff --git a/tests/buffer-count-test.c b/tests/buffer-count-test.c new file mode 100644 index 00000000..ad2bceeb --- /dev/null +++ b/tests/buffer-count-test.c @@ -0,0 +1,128 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "weston-test-client-helper.h" +#include +#include +#include + +#include +#include +#include + +struct test_data { + struct client *client; + + EGLDisplay egl_dpy; + EGLContext egl_ctx; + EGLConfig egl_conf; + EGLSurface egl_surface; +}; + +static void +init_egl(struct test_data *test_data) +{ + struct wl_egl_window *native_window; + struct surface *surface = test_data->client->surface; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 0, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLint major, minor, n; + EGLBoolean ret; + + test_data->egl_dpy = eglGetDisplay((EGLNativeDisplayType) + test_data->client->wl_display); + assert(test_data->egl_dpy); + + ret = eglInitialize(test_data->egl_dpy, &major, &minor); + assert(ret == EGL_TRUE); + ret = eglBindAPI(EGL_OPENGL_ES_API); + assert(ret == EGL_TRUE); + + ret = eglChooseConfig(test_data->egl_dpy, config_attribs, + &test_data->egl_conf, 1, &n); + assert(ret && n == 1); + + test_data->egl_ctx = eglCreateContext(test_data->egl_dpy, + test_data->egl_conf, + EGL_NO_CONTEXT, context_attribs); + assert(test_data->egl_ctx); + + native_window = + wl_egl_window_create(surface->wl_surface, + surface->width, + surface->height); + test_data->egl_surface = + eglCreateWindowSurface(test_data->egl_dpy, + test_data->egl_conf, + (EGLNativeWindowType) native_window, + NULL); + + ret = eglMakeCurrent(test_data->egl_dpy, test_data->egl_surface, + test_data->egl_surface, test_data->egl_ctx); + assert(ret == EGL_TRUE); +} + +TEST(test_buffer_count) +{ + struct test_data test_data; + uint32_t buffer_count; + int i; + + test_data.client = client_create(10, 10, 10, 10); + init_egl(&test_data); + + /* This is meant to represent a typical game loop which is + * expecting eglSwapBuffers to block and throttle the + * rendering to a sensible frame rate. Therefore it doesn't + * expect to have to install a frame callback itself. I'd + * imagine this is what a typical SDL game would end up + * doing */ + + for (i = 0; i < 10; i++) { + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(test_data.egl_dpy, test_data.egl_surface); + } + + buffer_count = get_n_egl_buffers(test_data.client); + + printf("buffers used = %i\n", buffer_count); + + /* The implementation should only end up creating two buffers + * and cycling between them */ + assert(buffer_count == 2); +} diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c index b19be400..fd265f2e 100644 --- a/tests/weston-test-client-helper.c +++ b/tests/weston-test-client-helper.c @@ -111,6 +111,17 @@ move_client(struct client *client, int x, int y) frame_callback_wait(client, &done); } +int +get_n_egl_buffers(struct client *client) +{ + client->test->n_egl_buffers = -1; + + wl_test_get_n_egl_buffers(client->test->wl_test); + wl_display_roundtrip(client->wl_display); + + return client->test->n_egl_buffers; +} + static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *wl_surface, @@ -340,8 +351,17 @@ test_handle_pointer_position(void *data, struct wl_test *wl_test, test->pointer_x, test->pointer_y); } +static void +test_handle_n_egl_buffers(void *data, struct wl_test *wl_test, uint32_t n) +{ + struct test *test = data; + + test->n_egl_buffers = n; +} + static const struct wl_test_listener test_listener = { - test_handle_pointer_position + test_handle_pointer_position, + test_handle_n_egl_buffers, }; static void diff --git a/tests/weston-test-client-helper.h b/tests/weston-test-client-helper.h index a5edca90..c78fc28b 100644 --- a/tests/weston-test-client-helper.h +++ b/tests/weston-test-client-helper.h @@ -51,6 +51,7 @@ struct test { struct wl_test *wl_test; int pointer_x; int pointer_y; + uint32_t n_egl_buffers; }; struct input { @@ -120,4 +121,7 @@ frame_callback_set(struct wl_surface *surface, int *done); void frame_callback_wait(struct client *client, int *done); +int +get_n_egl_buffers(struct client *client); + #endif diff --git a/tests/weston-test.c b/tests/weston-test.c index fc025fa6..844059dc 100644 --- a/tests/weston-test.c +++ b/tests/weston-test.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include #include @@ -28,6 +30,11 @@ #include "../src/compositor.h" #include "wayland-test-server-protocol.h" +#ifdef ENABLE_EGL +#include +#include +#endif /* ENABLE_EGL */ + struct weston_test { struct weston_compositor *compositor; struct weston_layer layer; @@ -181,12 +188,54 @@ send_key(struct wl_client *client, struct wl_resource *resource, notify_key(seat, 100, key, state, STATE_UPDATE_AUTOMATIC); } +#ifdef ENABLE_EGL +static int +is_egl_buffer(struct wl_resource *resource) +{ + PFNEGLQUERYWAYLANDBUFFERWL query_buffer = + (void *) eglGetProcAddress("eglQueryWaylandBufferWL"); + EGLint format; + + if (query_buffer(eglGetCurrentDisplay(), + resource, + EGL_TEXTURE_FORMAT, + &format)) + return 1; + + return 0; +} +#endif /* ENABLE_EGL */ + +static void +get_n_buffers(struct wl_client *client, struct wl_resource *resource) +{ + int n_buffers = 0; + +#ifdef ENABLE_EGL + struct wl_resource *buffer_resource; + int i; + + for (i = 0; i < 1000; i++) { + buffer_resource = wl_client_get_object(client, i); + + if (buffer_resource == NULL) + continue; + + if (is_egl_buffer(buffer_resource)) + n_buffers++; + } +#endif /* ENABLE_EGL */ + + wl_test_send_n_egl_buffers(resource, n_buffers); +} + static const struct wl_test_interface test_implementation = { move_surface, move_pointer, send_button, activate_surface, - send_key + send_key, + get_n_buffers, }; static void