From 1ab3e5a123109704789c2768e11a4f9af515821d Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Wed, 14 Oct 2026 13:13:52 +0300 Subject: Redefine public and rendering APIs with explicit contracts --- tests/common/test_gl.c | 44 ++--- tests/common/test_surface_integration.c | 302 ++++++++++++++++++++++++-------- tests/common/test_vulkan.c | 35 ++-- 3 files changed, 278 insertions(+), 103 deletions(-) (limited to 'tests/common') diff --git a/tests/common/test_gl.c b/tests/common/test_gl.c index cd51575..0e4597b 100644 --- a/tests/common/test_gl.c +++ b/tests/common/test_gl.c @@ -27,9 +27,10 @@ static yasl_surface *cpu; static void fail(const char *message, int line) { const char *description = NULL; - enum yasl_error error = yasl_get_error(&description); + int error = errno; + description = strerror(error); fprintf(stderr, "GL integration failure at line %d: %s (YASL error %d: %s, native error %d)\n", - line, message, error, description ? description : "none", yasl_get_native_error()); + line, message, error, description ? description : "none", errno); (void)yasl_gl_make_current(NULL); if (cpu) yasl_surface_destroy(cpu); if (shared) yasl_surface_destroy(shared); @@ -74,13 +75,13 @@ static void wait_for_size(yasl_surface *surface, int width, int height) int main(int argc, char **argv) { REQUIRE(argc == 2, "expected backend argument: wayland or x11"); - if (!strcmp(argv[1], "wayland")) REQUIRE(yasl_set_backend(YASL_BACKEND_WAYLAND), "select Wayland backend"); - else if (!strcmp(argv[1], "x11")) REQUIRE(yasl_set_backend(YASL_BACKEND_X11), "select X11 backend"); + if (!strcmp(argv[1], "wayland")) REQUIRE((yasl_init(&(struct yasl_options){.backend=YASL_BACKEND_WAYLAND}) == 0), "select Wayland backend"); + else if (!strcmp(argv[1], "x11")) REQUIRE((yasl_init(&(struct yasl_options){.backend=YASL_BACKEND_X11}) == 0), "select X11 backend"); else REQUIRE(false, "backend must be wayland or x11"); - primary = yasl_gl_surface_create("YASL GL test", 320, 240, 0, NULL, NULL); + primary = yasl_gl_surface_create(&(struct yasl_surface_options){.title="YASL GL test", .width=320, .height=240, .type=YASL_SURFACE_NATIVE, .flags=0}, NULL); REQUIRE(primary != NULL, "create default OpenGL 3.2 surface"); - REQUIRE(yasl_gl_make_current(primary), "make first GL context current"); + REQUIRE((yasl_gl_make_current(primary) == 0), "make first GL context current"); get_string_fn get_string = NULL; clear_color_fn clear_color = NULL; @@ -114,22 +115,24 @@ int main(int argc, char **argv) REQUIRE(abs((int)pixel[0] - 51) <= 3 && abs((int)pixel[1] - 102) <= 3 && abs((int)pixel[2] - 204) <= 3 && pixel[3] >= 250, "read rendered pixel from the native GL framebuffer"); - REQUIRE(yasl_gl_swap_interval(primary, 0), "disable swap interval"); - REQUIRE(yasl_gl_swap_buffers(primary), "swap first GL surface"); + REQUIRE((yasl_gl_set_swap_interval(primary, 0) == 0), "disable swap interval"); + REQUIRE((yasl_gl_present(primary) == 0), "swap first GL surface"); unsigned texture = 0; gen_textures(1, &texture); bind_texture(GL_TEXTURE_2D_, texture); REQUIRE(is_texture(texture), "create a shareable GL texture"); - shared = yasl_gl_surface_create("YASL GL shared context", 160, 120, 0, NULL, primary); + struct yasl_gl_options sharing = YASL_GL_OPTIONS_INIT; + sharing.share = primary; + shared = yasl_gl_surface_create(&(struct yasl_surface_options){.title="YASL GL shared context", .width=160, .height=120, .type=YASL_SURFACE_NATIVE, .flags=0}, &sharing); REQUIRE(shared != NULL, "create shared GL context"); - REQUIRE(yasl_gl_make_current(shared), "make shared context current"); + REQUIRE((yasl_gl_make_current(shared) == 0), "make shared context current"); REQUIRE(is_texture(texture), "verify context shares GL objects"); delete_textures(1, &texture); - REQUIRE(yasl_gl_make_current(primary), "restore primary GL context"); + REQUIRE((yasl_gl_make_current(primary) == 0), "restore primary GL context"); - REQUIRE(yasl_surface_request_size(primary, 400, 300), "request surface resize"); + REQUIRE((yasl_surface_request_size(primary, 400, 300) == 0), "request surface resize"); wait_for_size(primary, 400, 300); yasl_surface_get_framebuffer_size(primary, &pixel_width, &pixel_height); double scale = yasl_surface_get_scale(primary); @@ -138,18 +141,19 @@ int main(int argc, char **argv) "query resized framebuffer dimensions"); clear_color(0.7f, 0.1f, 0.3f, 1.0f); clear(GL_COLOR_BUFFER_BIT_); - REQUIRE(yasl_gl_swap_buffers(primary), "swap resized GL surface"); + REQUIRE((yasl_gl_present(primary) == 0), "swap resized GL surface"); - const int invalid_attributes[] = {0x7fff, 1, YASL_GL_END}; - REQUIRE(yasl_gl_surface_create("invalid attrs", 100, 100, 0, invalid_attributes, NULL) == NULL, - "reject unknown GL context attributes"); - REQUIRE(yasl_gl_surface_create("invalid CPU GL", 100, 100, YASL_SURFACE_CPU, NULL, NULL) == NULL, + struct yasl_gl_options invalid_options = YASL_GL_OPTIONS_INIT; + invalid_options.major = -1; + REQUIRE(yasl_gl_surface_create(&(struct yasl_surface_options){.title="invalid attrs", .width=100, .height=100, .type=YASL_SURFACE_NATIVE, .flags=0}, &invalid_options) == NULL, + "reject invalid GL context options"); + REQUIRE(yasl_gl_surface_create(&(struct yasl_surface_options){.title="invalid CPU GL", .width=100, .height=100, .type=YASL_SURFACE_CPU, .flags=0}, NULL) == NULL, "reject CPU flag on GL surface creation"); - cpu = yasl_surface_create("CPU surface", 100, 100, YASL_SURFACE_CPU); + cpu = yasl_surface_create(&(struct yasl_surface_options){.title="CPU surface", .width=100, .height=100, .type=YASL_SURFACE_CPU, .flags=0}); REQUIRE(cpu != NULL, "create CPU surface for incompatibility check"); - REQUIRE(!yasl_gl_make_current(cpu), "reject CPU surface as a GL context"); + REQUIRE((yasl_gl_make_current(cpu) < 0), "reject CPU surface as a GL context"); - REQUIRE(yasl_gl_make_current(NULL), "detach GL context before destruction"); + REQUIRE((yasl_gl_make_current(NULL) == 0), "detach GL context before destruction"); yasl_surface_destroy(cpu); cpu = NULL; yasl_surface_destroy(shared); shared = NULL; yasl_surface_destroy(primary); primary = NULL; diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c index 7cc938a..1f18f23 100644 --- a/tests/common/test_surface_integration.c +++ b/tests/common/test_surface_integration.c @@ -2,6 +2,16 @@ #include #include #include +#include +#if YASL_HAS_WAYLAND +#include +#endif +#if YASL_HAS_X11 +#include +#endif +#if YASL_HAS_COCOA +#include +#endif #include "common/backend.h" #include #include @@ -14,95 +24,241 @@ void yasl_test_frame_tick(struct yasl_surface *surface); #endif static void drain(void) { - yasl_event e;int n=0; - while(yasl_wait_event(&e,0)>0)assert(++n<1000); + yasl_event e; + int n = 0; + while (yasl_wait_event(&e, 0) > 0) + assert(++n < 1000); } static void *wake_thread(void *unused) -{ (void)unused;struct timespec delay={0,20000000};nanosleep(&delay,NULL);yasl_wake();return NULL; } +{ + (void)unused; + struct timespec delay = {0, 20000000}; + nanosleep(&delay, NULL); + yasl_wake(); + return NULL; +} static void *wrong_thread(void *data) -{ assert(!yasl_surface_set_title(data,"wrong"));assert(yasl_get_error(NULL)==YASL_ERROR_WRONG_THREAD);return NULL; } +{ + assert(yasl_surface_set_title(data, "wrong") == -EPERM); + struct yasl_cpu_buffer buffer; + assert(yasl_cpu_acquire(data, &buffer) == -EPERM && !buffer.pixels); +#if YASL_HAS_WAYLAND + struct yasl_wayland_handles native; + assert(yasl_wayland_get_native(data, &native) == -EPERM && !native.display && !native.surface); +#endif + return NULL; +} static int refreshes; -static void refresh(yasl_surface *s,void *ud) +static void refresh(yasl_surface *s, void *ud) { - (void)ud;refreshes++; - yasl_event e;assert(yasl_wait_event(&e,0)==-1);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); - yasl_surface_destroy(s);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); + (void)ud; + refreshes++; + yasl_event e; + assert(yasl_wait_event(&e, 0) == -EBUSY); + assert(errno == EBUSY); + assert(yasl_surface_destroy(s) == -EBUSY); + struct yasl_surface_options options = {.width = 32, .height = 32}; + assert(!yasl_surface_create(&options) && errno == EBUSY); + assert(!yasl_gl_surface_create(&options, NULL) && errno == EBUSY); } -int main(int argc,char **argv) +int main(int argc, char **argv) { - assert(argc==2); - enum yasl_backend backend=!strcmp(argv[1],"wayland")?YASL_BACKEND_WAYLAND:!strcmp(argv[1],"x11")?YASL_BACKEND_X11:YASL_BACKEND_COCOA; - assert(yasl_set_backend(backend));assert(yasl_set_app_id("org.yasl.surface-test")); - yasl_surface *s=yasl_surface_create("CPU contract",96,80,YASL_SURFACE_CPU); - if(!s){const char *why;yasl_get_error(&why);fprintf(stderr,"surface: %s native=%d\n",why,yasl_get_native_error());return 1;} - assert(yasl_surface_backend(s)==backend); - if(backend==YASL_BACKEND_COCOA) { - assert(!(yasl_surface_features(s)&YASL_CAP_OPENGL)); - assert(!yasl_gl_surface_create("unsupported GL",64,64,0,NULL,NULL)); - assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); - assert(!yasl_gl_make_current(NULL)); - assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + assert(argc == 2); + enum yasl_backend backend = !strcmp(argv[1], "wayland") ? YASL_BACKEND_WAYLAND + : !strcmp(argv[1], "x11") ? YASL_BACKEND_X11 + : YASL_BACKEND_COCOA; + assert(yasl_init( + &(struct yasl_options){.backend = backend, .app_id = "org.yasl.surface-test"}) == 0); + yasl_surface *s = yasl_surface_create(&(struct yasl_surface_options){ + .title = "CPU contract", .width = 96, .height = 80, .type = YASL_SURFACE_CPU, .flags = 0}); + if (!s) { + const char *why; + why = strerror(errno); + fprintf(stderr, "surface: %s native=%d\n", why, errno); + return 1; + } + assert(yasl_surface_get_backend(s) == backend); + assert(yasl_surface_set_userdata(s, &backend) == 0); + assert(yasl_surface_get_userdata(s) == &backend); +#if YASL_HAS_WAYLAND + struct yasl_wayland_handles wl; + int wl_result = yasl_wayland_get_native(s, &wl); + assert(wl_result == (backend == YASL_BACKEND_WAYLAND ? 0 : -ENOTSUP)); + assert(backend == YASL_BACKEND_WAYLAND ? wl.display && wl.surface : !wl.display && !wl.surface); + assert(yasl_wayland_get_native(s, NULL) == -EINVAL); +#endif +#if YASL_HAS_X11 + struct yasl_x11_handles x; + int x_result = yasl_x11_get_native(s, &x); + assert(x_result == (backend == YASL_BACKEND_X11 ? 0 : -ENOTSUP)); + assert(backend == YASL_BACKEND_X11 ? x.display && x.window : !x.display && !x.window); +#endif +#if YASL_HAS_COCOA + struct yasl_cocoa_handles cocoa; + assert(yasl_cocoa_get_native(s, &cocoa) == 0 && cocoa.application && cocoa.window && + cocoa.view); +#endif + CAMetalLayer *layer = NULL; + assert(yasl_metal_get_layer(s, &layer) == -EBUSY && !layer); + assert(yasl_surface_set_ime_caret(s, 1e300, 0, 1, 1) == -EOVERFLOW); + if (backend == YASL_BACKEND_COCOA) { + assert(!(yasl_surface_get_features(s) & YASL_CAP_OPENGL)); + assert(!yasl_gl_surface_create(&(struct yasl_surface_options){.title = "unsupported GL", + .width = 64, + .height = 64, + .type = YASL_SURFACE_NATIVE, + .flags = 0}, + NULL)); + assert(errno == ENOTSUP); + assert((yasl_gl_make_current(NULL) < 0)); + assert(errno == ENOTSUP); assert(!yasl_gl_get_proc_address("glClear")); - assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + assert(errno == ENOTSUP); } /* The first events report the window size, then ask for a frame. */ - yasl_event e;int fw=0,fh=0;bool window=false; - for(int i=0;i<1000;i++) { - assert(yasl_wait_event(&e,i?20:0)>=0); - if(e.type==YASL_EVENT_WINDOW){window=true;fw=e.window.pixel_width;fh=e.window.pixel_height;} - if(e.type==YASL_EVENT_REFRESH){assert(window&&fw>0&&fh>0&&e.surface==s);break;} + yasl_event e; + int fw = 0, fh = 0; + bool window = false; + for (int i = 0; i < 1000; i++) { + assert(yasl_wait_event(&e, i ? 20 : 0) >= 0); + if (e.type == YASL_EVENT_WINDOW) { + window = true; + fw = e.window.pixel_width; + fh = e.window.pixel_height; + } + if (e.type == YASL_EVENT_REFRESH) { + assert(window && fw > 0 && fh > 0 && e.surface == s); + break; + } } - assert(e.type==YASL_EVENT_REFRESH); - int w,h;yasl_surface_get_framebuffer_size(s,&w,&h);assert(w==fw&&h==fh); - assert(!yasl_set_backend(backend));assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); - int pw,ph;uint32_t *pixels=yasl_cpu_pixels(s,&pw,&ph);assert(pixels&&pw==w&&ph==h); - assert(pixels[0]==0&&pixels[(size_t)w*h-1]==0); - for(size_t i=0;i<(size_t)w*h;i++)pixels[i]=0xff102030u; - pixels[(size_t)3*w+2]=0xffaabbccu; - assert(yasl_cpu_present(s)); - assert(yasl_cpu_pixels(s,&pw,&ph)==pixels&&pixels[0]==0xff102030u&&pixels[(size_t)3*w+2]==0xffaabbccu); + assert(e.type == YASL_EVENT_REFRESH); + int w, h; + yasl_surface_get_framebuffer_size(s, &w, &h); + assert(w == fw && h == fh); + assert((yasl_init(&(struct yasl_options){.backend = backend}) < 0)); + assert(errno == EALREADY); + struct yasl_cpu_buffer buffer, other; + assert(yasl_cpu_acquire(s, &buffer) == 0); + uint32_t *pixels = buffer.pixels; + assert(buffer.width == w && buffer.height == h && buffer.stride_bytes == (size_t)w * 4); + assert(pixels[0] == 0 && pixels[(size_t)w * h - 1] == 0); + assert(yasl_cpu_acquire(s, &other) == -EBUSY && !other.pixels); + for (size_t i = 0; i < (size_t)w * h; i++) + pixels[i] = 0xff102030u; + pixels[(size_t)3 * w + 2] = 0xffaabbccu; + other = buffer; + other.stride_bytes++; + assert(yasl_cpu_present(s, &other) == -EINVAL); + assert(yasl_cpu_present(s, &buffer) == 0); + assert(yasl_cpu_present(s, &buffer) == -ESTALE); + assert(yasl_cpu_acquire(s, &buffer) == 0); + assert(buffer.pixels[0] == 0xff102030u && buffer.pixels[(size_t)3 * w + 2] == 0xffaabbccu); + buffer.pixels[0] = 0xffffffffu; + assert(s->committed_pixels[0] == 0xff102030u); + assert(yasl_cpu_discard(s, &buffer) == 0); + assert(yasl_cpu_discard(s, &buffer) == -ESTALE); + assert(yasl_cpu_acquire(s, &buffer) == 0 && buffer.pixels[0] == 0xff102030u); drain(); - pthread_t thread;assert(!pthread_create(&thread,NULL,wrong_thread,s));pthread_join(thread,NULL); - assert(!pthread_create(&thread,NULL,wake_thread,NULL)); - int n=yasl_wait_event(&e,500);assert(n>=0);pthread_join(thread,NULL); - bool ime=yasl_surface_set_text_input(s,true,YASL_TEXT_NORMAL); - if(!ime)assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); - bool snapshot=yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,1,3,7); - if(ime)assert(snapshot); - else assert(!snapshot&&yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); - assert(!yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,2,3,8)); - assert(!yasl_surface_set_surrounding_text(s,"\xc0\xaf",2,0,2,8)); + assert(yasl_cpu_present(s, &buffer) == -ESTALE); + yasl_surface *second = yasl_surface_create(&(struct yasl_surface_options){ + .width = 32, .height = 32, .type = YASL_SURFACE_CPU, .userdata = &backend}); + assert(second && yasl_surface_get_userdata(second) == &backend); + assert(yasl_cpu_acquire(s, &buffer) == 0); + assert(yasl_cpu_acquire(second, &other) == 0); + assert(yasl_cpu_present(second, &buffer) == -ESTALE); + assert(yasl_cpu_discard(second, &other) == 0); + assert(yasl_surface_destroy(second) == 0); + assert(yasl_cpu_discard(s, &buffer) == 0); + pthread_t thread; + assert(!pthread_create(&thread, NULL, wrong_thread, s)); + pthread_join(thread, NULL); + assert(!pthread_create(&thread, NULL, wake_thread, NULL)); + int n = yasl_wait_event(&e, 500); + assert(n >= 0); + pthread_join(thread, NULL); + bool ime = (yasl_surface_set_text_input(s, true, YASL_TEXT_NORMAL) == 0); + if (!ime) + assert(errno == ENOTSUP); + bool snapshot = (yasl_surface_set_surrounding_text(s, "a\xc3\xa9z", 4, 1, 3, 7) == 0); + if (ime) + assert(snapshot); + else + assert(!snapshot && errno == ENOTSUP); + assert((yasl_surface_set_surrounding_text(s, "a\xc3\xa9z", 4, 2, 3, 8) < 0)); + assert((yasl_surface_set_surrounding_text(s, "\xc0\xaf", 2, 0, 2, 8) < 0)); drain(); - struct yasl_private_event pen={.type=YASL_PRIVATE_EVENT_PEN,.surface=s, - .pen={.device_id=10,.tool_id=20,.x=12.5,.y=9.25,.pressure=0.3, - .axes_valid=YASL_PRIVATE_PEN_PRESSURE,.action=YASL_PRIVATE_PEN_DOWN,.in_contact=true}}; - assert(yasl_private_events_push(s->display,s,&pen)); - assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_PEN&&e.pen.device_id==10&&e.pen.pressure==0.3&&e.pen.in_contact); - struct yasl_private_event text={.type=YASL_PRIVATE_EVENT_TEXT,.surface=s,.text={.data="owned",.len=5}}; - assert(yasl_private_events_push(s->display,s,&text));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_TEXT); - assert(e.text.length==5&&!strcmp(e.text.data,"owned")); + struct yasl_private_event pen = {.type = YASL_PRIVATE_EVENT_PEN, + .surface = s, + .pen = {.device_id = 10, + .tool_id = 20, + .x = 12.5, + .y = 9.25, + .pressure = 0.3, + .axes_valid = YASL_PRIVATE_PEN_PRESSURE, + .action = YASL_PRIVATE_PEN_DOWN, + .in_contact = true}}; + assert(yasl_private_events_push(s->display, s, &pen)); + assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_PEN && e.pen.device_id == 10 && + e.pen.pressure == 0.3 && e.pen.in_contact); + struct yasl_private_event text = { + .type = YASL_PRIVATE_EVENT_TEXT, .surface = s, .text = {.data = "owned", .len = 5}}; + assert(yasl_private_events_push(s->display, s, &text)); + assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_TEXT); + assert(e.text.length == 5 && !strcmp(e.text.data, "owned")); /* Unchanged focus folds into no event; a change reports the activated state. */ - unsigned active=yasl_surface_state(s)&YASL_STATE_ACTIVATED; - struct yasl_private_event focus={.type=YASL_PRIVATE_EVENT_FOCUS,.surface=s,.focus={.focused=!active}}; - assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_WINDOW); - assert((e.window.state&YASL_STATE_ACTIVATED)==(active?0u:YASL_STATE_ACTIVATED)&&e.window.pixel_width==w); - assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==0&&e.type==YASL_EVENT_NONE); - struct yasl_private_event hover={.type=YASL_PRIVATE_EVENT_DROP_HOVER,.surface=s,.drop={YASL_PRIVATE_DROP_LEAVE,{0,0}}}; - assert(yasl_private_events_push(s->display,s,&hover)); - assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_DROP&&e.drop.action==YASL_DROP_LEAVE); - yasl_surface_set_refresh_callback(s,refresh,NULL); - assert(yasl_cpu_present(s)); + unsigned active = yasl_surface_get_state(s) & YASL_STATE_ACTIVATED; + struct yasl_private_event focus = { + .type = YASL_PRIVATE_EVENT_FOCUS, .surface = s, .focus = {.focused = !active}}; + assert(yasl_private_events_push(s->display, s, &focus)); + assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_WINDOW); + assert((e.window.state & YASL_STATE_ACTIVATED) == (active ? 0u : YASL_STATE_ACTIVATED) && + e.window.pixel_width == w); + assert(yasl_private_events_push(s->display, s, &focus)); + assert(yasl_wait_event(&e, 0) == 0 && e.type == YASL_EVENT_NONE); + struct yasl_private_event hover = {.type = YASL_PRIVATE_EVENT_DROP_HOVER, + .surface = s, + .drop = {YASL_PRIVATE_DROP_LEAVE, {0, 0}}}; + assert(yasl_private_events_push(s->display, s, &hover)); + assert(yasl_wait_event(&e, 0) == 1 && e.type == YASL_EVENT_DROP && + e.drop.action == YASL_DROP_LEAVE); + assert(yasl_surface_request_size(s, 112, 96) == 0); + uint64_t resize_deadline = yasl_time_ns() + 3000000000ull; + int logical_w = 0, logical_h = 0; + do { + assert(yasl_wait_event(&e, 20) >= 0); + yasl_surface_get_size(s, &logical_w, &logical_h); + } while ((logical_w != 112 || logical_h != 96) && yasl_time_ns() < resize_deadline); + assert(logical_w == 112 && logical_h == 96); + assert(yasl_cpu_acquire(s, &buffer) == 0); + assert(buffer.pixels[0] == 0xff102030u); + assert(buffer.pixels[(size_t)3 * buffer.width + 2] == 0xffaabbccu); + assert(buffer.pixels[(size_t)buffer.width * buffer.height - 1] == 0); + assert(yasl_cpu_present(s, &buffer) == 0); + yasl_surface_set_refresh_callback(s, refresh, NULL); + assert(yasl_cpu_acquire(s, &buffer) == 0); + assert(yasl_cpu_present(s, &buffer) == 0); #if YASL_HAS_COCOA yasl_test_frame_tick(s); #endif - uint64_t deadline=yasl_private_loop_now_ns()+3000000000ull; - while(!refreshes && yasl_private_loop_now_ns()=0); - assert(refreshes>0); - yasl_surface_set_refresh_callback(s,NULL,NULL); + uint64_t deadline = yasl_private_loop_now_ns() + 3000000000ull; + while (!refreshes && yasl_private_loop_now_ns() < deadline) + assert(yasl_wait_event(&e, 20) >= 0); + assert(refreshes > 0); + yasl_surface_set_refresh_callback(s, NULL, NULL); yasl_surface_destroy(s); - assert(!yasl_set_backend(backend)); - s=yasl_surface_create("shared backend remains",64,64,YASL_SURFACE_CPU);assert(s); - yasl_shutdown();assert(yasl_set_backend(backend)); - s=yasl_surface_create("reinitialized",64,64,YASL_SURFACE_CPU);assert(s);yasl_shutdown(); - puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed");return 0; + assert((yasl_init(&(struct yasl_options){.backend = backend}) < 0)); + s = yasl_surface_create(&(struct yasl_surface_options){.title = "shared backend remains", + .width = 64, + .height = 64, + .type = YASL_SURFACE_CPU, + .flags = 0}); + assert(s); + yasl_shutdown(); + assert((yasl_init(&(struct yasl_options){.backend = backend}) == 0)); + s = yasl_surface_create(&(struct yasl_surface_options){ + .title = "reinitialized", .width = 64, .height = 64, .type = YASL_SURFACE_CPU, .flags = 0}); + assert(s); + yasl_shutdown(); + puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed"); + return 0; } diff --git a/tests/common/test_vulkan.c b/tests/common/test_vulkan.c index 12daa22..b12256a 100644 --- a/tests/common/test_vulkan.c +++ b/tests/common/test_vulkan.c @@ -41,29 +41,32 @@ static int run_test(enum yasl_backend backend) VkSemaphore acquired = VK_NULL_HANDLE, rendered = VK_NULL_HANDLE; VkCommandBuffer command = VK_NULL_HANDLE; - if (!yasl_set_backend(backend)) { + if ((yasl_init(&(struct yasl_options){.backend=backend}) < 0)) { fprintf(stderr, "vulkan integration: cannot select requested backend %d (YASL error %d)\n", - backend, yasl_get_error(NULL)); + backend, errno); goto cleanup; } - if (!yasl_vulkan_init(vkGetInstanceProcAddr)) { + if ((yasl_vulkan_init(vkGetInstanceProcAddr) < 0)) { fprintf(stderr, "vulkan integration: loader initialization failed (YASL error %d)\n", - yasl_get_error(NULL)); + errno); goto cleanup; } - surface = yasl_surface_create("yasl Vulkan WSI integration", 256, 192, 0); + surface = yasl_surface_create(&(struct yasl_surface_options){.title="yasl Vulkan WSI integration", .width=256, .height=192, .type=YASL_SURFACE_NATIVE, .flags=0}); if (!surface) { fprintf(stderr, "vulkan integration: surface creation failed (YASL error %d)\n", - yasl_get_error(NULL)); + errno); goto cleanup; } - if (!(yasl_surface_features(surface) & YASL_CAP_VULKAN)) { + if (!(yasl_surface_get_features(surface) & YASL_CAP_VULKAN)) { fprintf(stderr, "vulkan integration: requested backend does not advertise Vulkan WSI\n"); goto cleanup; } uint32_t extension_count = 0; - const char *const *required = yasl_vulkan_instance_extensions(surface, &extension_count); + struct yasl_vulkan_requirements requirements; + if (yasl_vulkan_get_requirements(surface, &requirements) < 0) goto cleanup; + extension_count = requirements.extension_count; + const char *const *required = requirements.extensions; if (!required || !extension_count) { fprintf(stderr, "vulkan integration: surface returned no required instance extensions\n"); goto cleanup; @@ -99,7 +102,7 @@ static int run_test(enum yasl_backend backend) VkInstanceCreateInfo instance_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &app, - .flags = yasl_vulkan_instance_flags(surface), + .flags = requirements.flags, .enabledExtensionCount = extension_count, .ppEnabledExtensionNames = required, }; @@ -108,6 +111,18 @@ static int run_test(enum yasl_backend backend) vr = yasl_vulkan_create_surface(surface, instance, NULL, &vk_surface); if (vr != VK_SUCCESS) { status = fail_vk("yasl_vulkan_create_surface", vr); goto cleanup; } + VkSurfaceKHR duplicate = VK_NULL_HANDLE; + if (yasl_vulkan_create_surface(surface, instance, NULL, &duplicate) != VK_ERROR_NATIVE_WINDOW_IN_USE_KHR || + duplicate != VK_NULL_HANDLE || yasl_surface_destroy(surface) != -EBUSY || + yasl_shutdown() != -EBUSY || yasl_vulkan_init(vkGetInstanceProcAddr) != -EBUSY) { + fprintf(stderr, "vulkan integration: live WSI ownership was not enforced\n"); + goto cleanup; + } + if (yasl_vulkan_destroy_surface(surface) != 0 || yasl_vulkan_destroy_surface(surface) != 0) goto cleanup; + vk_surface = VK_NULL_HANDLE; + vr = yasl_vulkan_create_surface(surface, instance, NULL, &vk_surface); + if (vr != VK_SUCCESS) { status = fail_vk("recreate Vulkan surface", vr); goto cleanup; } + uint32_t physical_count = 0; vr = vkEnumeratePhysicalDevices(instance, &physical_count, NULL); if (vr != VK_SUCCESS || !physical_count) { @@ -365,7 +380,7 @@ cleanup: if (command_pool) vkDestroyCommandPool(device, command_pool, NULL); if (swapchain) vkDestroySwapchainKHR(device, swapchain, NULL); if (device) vkDestroyDevice(device, NULL); - if (vk_surface) vkDestroySurfaceKHR(instance, vk_surface, NULL); + if (vk_surface) yasl_vulkan_destroy_surface(surface); if (instance) vkDestroyInstance(instance, NULL); if (surface) yasl_surface_destroy(surface); yasl_shutdown(); -- cgit v1.2.3