summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.co.uk>2014-09-23 22:08:48 -0400
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>2014-09-30 13:02:20 +0300
commitde7f5c8fda22757662b4e52cdf5a7b7c7520a7f6 (patch)
tree4abf5dddd8a5186f81d590e78abbdbaace06b626
parent641307ca2190fbb1aded28fe0f95c0d9cdab1338 (diff)
tests: presentation test, simple
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
-rw-r--r--Makefile.am8
-rw-r--r--tests/presentation-test.c247
2 files changed, 255 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 6a91a8f8..87204a68 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -842,6 +842,7 @@ weston_tests = \
event.weston \
button.weston \
text.weston \
+ presentation.weston \
subsurface.weston
@@ -944,6 +945,13 @@ subsurface_weston_SOURCES = tests/subsurface-test.c
subsurface_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
subsurface_weston_LDADD = libtest-client.la
+presentation_weston_SOURCES = tests/presentation-test.c
+nodist_presentation_weston_SOURCES = \
+ protocol/presentation_timing-protocol.c \
+ protocol/presentation_timing-client-protocol.h
+presentation_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
+presentation_weston_LDADD = libtest-client.la
+
if ENABLE_EGL
weston_tests += buffer-count.weston
buffer_count_weston_SOURCES = tests/buffer-count-test.c
diff --git a/tests/presentation-test.c b/tests/presentation-test.c
new file mode 100644
index 00000000..44080822
--- /dev/null
+++ b/tests/presentation-test.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright © 2014 Collabora, Ltd.
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "weston-test-client-helper.h"
+#include "presentation_timing-client-protocol.h"
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+static inline void *
+xzalloc(size_t size)
+{
+ void *p;
+
+ p = calloc(1, size);
+ assert(p);
+
+ return p;
+}
+
+static struct presentation *
+get_presentation(struct client *client)
+{
+ struct global *g;
+ struct global *global_pres = NULL;
+ static struct presentation *pres;
+
+ if (pres)
+ return pres;
+
+ wl_list_for_each(g, &client->global_list, link) {
+ if (strcmp(g->interface, "presentation"))
+ continue;
+
+ if (global_pres)
+ assert(0 && "multiple presentation objects");
+
+ global_pres = g;
+ }
+
+ assert(global_pres && "no presentation found");
+
+ assert(global_pres->version == 1);
+
+ pres = wl_registry_bind(client->wl_registry, global_pres->name,
+ &presentation_interface, 1);
+ assert(pres);
+
+ return pres;
+}
+
+struct feedback {
+ struct client *client;
+ struct presentation_feedback *obj;
+
+ enum {
+ FB_PENDING = 0,
+ FB_PRESENTED,
+ FB_DISCARDED
+ } result;
+
+ struct wl_output *sync_output;
+ uint64_t seq;
+ struct timespec time;
+ uint32_t refresh_nsec;
+ uint32_t flags;
+};
+
+static void
+timespec_from_proto(struct timespec *tm, uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo, uint32_t tv_nsec)
+{
+ tm->tv_sec = ((uint64_t)tv_sec_hi << 32) + tv_sec_lo;
+ tm->tv_nsec = tv_nsec;
+}
+
+static void
+feedback_sync_output(void *data,
+ struct presentation_feedback *presentation_feedback,
+ struct wl_output *output)
+{
+ struct feedback *fb = data;
+
+ assert(fb->result == FB_PENDING);
+
+ if (output)
+ fb->sync_output = output;
+}
+
+static void
+feedback_presented(void *data,
+ struct presentation_feedback *presentation_feedback,
+ uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec,
+ uint32_t refresh_nsec,
+ uint32_t seq_hi,
+ uint32_t seq_lo,
+ uint32_t flags)
+{
+ struct feedback *fb = data;
+
+ assert(fb->result == FB_PENDING);
+ fb->result = FB_PRESENTED;
+ fb->seq = ((uint64_t)seq_hi << 32) + seq_lo;
+ timespec_from_proto(&fb->time, tv_sec_hi, tv_sec_lo, tv_nsec);
+ fb->refresh_nsec = refresh_nsec;
+ fb->flags = flags;
+}
+
+static void
+feedback_discarded(void *data,
+ struct presentation_feedback *presentation_feedback)
+{
+ struct feedback *fb = data;
+
+ assert(fb->result == FB_PENDING);
+ fb->result = FB_DISCARDED;
+}
+
+static const struct presentation_feedback_listener feedback_listener = {
+ feedback_sync_output,
+ feedback_presented,
+ feedback_discarded
+};
+
+static struct feedback *
+feedback_create(struct client *client, struct wl_surface *surface)
+{
+ struct feedback *fb;
+
+ fb = xzalloc(sizeof *fb);
+ fb->client = client;
+ fb->obj = presentation_feedback(get_presentation(client), surface);
+ presentation_feedback_add_listener(fb->obj, &feedback_listener, fb);
+
+ return fb;
+}
+
+static void
+feedback_wait(struct feedback *fb)
+{
+ while (fb->result == FB_PENDING) {
+ assert(wl_display_dispatch(fb->client->wl_display) >= 0);
+ }
+}
+
+static char *
+pflags_to_str(uint32_t flags, char *str, unsigned len)
+{
+ static const struct {
+ uint32_t flag;
+ char sym;
+ } desc[] = {
+ { 1, '1' }, /* dummy placeholder */
+ };
+ unsigned i;
+
+ *str = '\0';
+ if (len < ARRAY_LENGTH(desc) + 1)
+ return str;
+
+ for (i = 0; i < ARRAY_LENGTH(desc); i++)
+ str[i] = flags & desc[i].flag ? desc[i].sym : '_';
+ str[ARRAY_LENGTH(desc)] = '\0';
+
+ return str;
+}
+
+static void
+feedback_print(struct feedback *fb)
+{
+ char str[10];
+
+ switch (fb->result) {
+ case FB_PENDING:
+ printf("pending");
+ return;
+ case FB_DISCARDED:
+ printf("discarded");
+ return;
+ case FB_PRESENTED:
+ break;
+ }
+
+ pflags_to_str(fb->flags, str, sizeof str);
+ printf("presented %lld.%09lld, refresh %u us, [%s] seq %" PRIu64,
+ (long long)fb->time.tv_sec, (long long)fb->time.tv_nsec,
+ fb->refresh_nsec / 1000, str, fb->seq);
+}
+
+static void
+feedback_destroy(struct feedback *fb)
+{
+ presentation_feedback_destroy(fb->obj);
+ free(fb);
+}
+
+TEST(test_presentation_feedback_simple)
+{
+ struct client *client;
+ struct feedback *fb;
+
+ client = client_create(100, 50, 123, 77);
+ assert(client);
+
+ wl_surface_attach(client->surface->wl_surface,
+ client->surface->wl_buffer, 0, 0);
+ fb = feedback_create(client, client->surface->wl_surface);
+ wl_surface_damage(client->surface->wl_surface, 0, 0, 100, 100);
+ wl_surface_commit(client->surface->wl_surface);
+
+ client_roundtrip(client);
+
+ feedback_wait(fb);
+
+ printf("%s feedback:", __func__);
+ feedback_print(fb);
+ printf("\n");
+
+ feedback_destroy(fb);
+}