diff options
Diffstat (limited to 'tests/common/test_backends.c')
| -rw-r--r-- | tests/common/test_backends.c | 52 |
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); |
