summaryrefslogtreecommitdiff
path: root/tests/common/test_backends.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/common/test_backends.c')
-rw-r--r--tests/common/test_backends.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/common/test_backends.c b/tests/common/test_backends.c
index 74860c8..30f9b67 100644
--- a/tests/common/test_backends.c
+++ b/tests/common/test_backends.c
@@ -112,6 +112,15 @@ static void configure(struct yasl_surface *s, struct yasl_geometry geometry, voi
if (w->destroy_on_configure) { yasl_surface_destroy(s); w->surface = NULL; }
}
+static void draw_without_present(struct yasl_surface *s, struct yasl_frame *frame, void *ud)
+{
+ (void)s;
+ struct window *w = ud;
+ size_t count = (size_t)frame->target.size.x * (size_t)frame->target.size.y;
+ for (size_t i = 0; i < count; i++) frame->target.pixels[i] = 0xff000000;
+ w->draws++;
+}
+
static void close_window(struct yasl_surface *s, void *ud)
{
struct window *w = ud;
@@ -146,6 +155,48 @@ static struct window create(struct yasl_display *d)
return (struct window){.surface = s, .display = d};
}
+/* The last presented frame reads back until a later draw replaces it. */
+static void test_read_pixels(struct yasl_loop *loop, struct yasl_display *d, struct window *w)
+{
+ struct yasl_vector2i size = {-1, -1};
+ assert(!yasl_surface_read_pixels(w->surface, NULL, 0, NULL));
+ assert(!yasl_surface_read_pixels(NULL, NULL, 0, &size) && !size.x && !size.y);
+ assert(!yasl_surface_read_pixels(w->surface, NULL, 0, &size));
+ struct yasl_vector2i extent = yasl_surface_geometry(w->surface).size;
+ assert(size.x == extent.x && size.y == extent.y);
+ size_t count = (size_t)size.x * (size_t)size.y;
+ uint32_t *pixels = calloc(count, sizeof(*pixels));
+ assert(pixels);
+ assert(!yasl_surface_read_pixels(w->surface, pixels, count - 1, &size));
+ assert(!pixels[0]);
+ assert(yasl_surface_read_pixels(w->surface, pixels, count, &size));
+ for (size_t i = 0; i < count; i++) assert(pixels[i] == 0xff4080c0);
+
+ /* Draws that never present must not show through. X11 reuses its one
+ * target; Wayland keeps the presented buffer while the compositor holds it. */
+ struct yasl_window_cbs skip = callbacks;
+ skip.draw = draw_without_present;
+ yasl_surface_set_callbacks(w->surface, &skip, w);
+ for (int i = 0; i < 4; i++) {
+ yasl_surface_schedule_redraw(w->surface);
+ pump(loop, d, NULL);
+ if (yasl_surface_read_pixels(w->surface, pixels, count, &size)) {
+ assert(yasl_display_backend(d) != YASL_BACKEND_X11);
+ for (size_t j = 0; j < count; j++) assert(pixels[j] == 0xff4080c0);
+ } else {
+ assert(!size.x && !size.y);
+ }
+ }
+
+ attach(w);
+ yasl_surface_schedule_redraw(w->surface);
+ pump(loop, d, NULL);
+ memset(pixels, 0, count * sizeof(*pixels));
+ assert(yasl_surface_read_pixels(w->surface, pixels, count, &size));
+ assert(pixels[0] == 0xff4080c0 && pixels[count - 1] == 0xff4080c0);
+ free(pixels);
+}
+
static void test_window_spec(struct yasl_loop *loop, struct yasl_display *d)
{
struct window w = {.display = d, .destroy_on_draw = true};
@@ -427,6 +478,7 @@ int main(int argc, char **argv)
yasl_surface_schedule_redraw(w.surface);
pump(loop, d, NULL);
assert(w.draws > 0);
+ test_read_pixels(loop, d, &w);
if (yasl_display_backend(d) == YASL_BACKEND_X11)
x11_behavior(loop, d, &w);
if (w.surface) yasl_surface_destroy(w.surface);