summaryrefslogtreecommitdiff
path: root/tests/common/test_surface_integration.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-14 13:13:52 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-14 13:13:52 +0300
commit1ab3e5a123109704789c2768e11a4f9af515821d (patch)
tree31ee03e58093a58100c6eb58681d5d29648a5ddd /tests/common/test_surface_integration.c
parentd86fa6215d40caa7852dbbd6a8cf4aa8e89dd879 (diff)
Redefine public and rendering APIs with explicit contracts
Diffstat (limited to 'tests/common/test_surface_integration.c')
-rw-r--r--tests/common/test_surface_integration.c302
1 files changed, 229 insertions, 73 deletions
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 <yasl/yasl.h>
#include <yasl/cpu.h>
#include <yasl/gl.h>
+#include <yasl/metal.h>
+#if YASL_HAS_WAYLAND
+#include <yasl/native/wayland.h>
+#endif
+#if YASL_HAS_X11
+#include <yasl/native/x11.h>
+#endif
+#if YASL_HAS_COCOA
+#include <yasl/native/cocoa.h>
+#endif
#include "common/backend.h"
#include <assert.h>
#include <pthread.h>
@@ -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()<deadline)assert(yasl_wait_event(&e,20)>=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;
}