From fecd704833b996e02b8029235a5d0a25a85a28e5 Mon Sep 17 00:00:00 2001 From: Artem Senichev Date: Sun, 15 Sep 2024 11:12:21 +0300 Subject: [PATCH] Fix multithreading drawing Handles the first task in the current thread. Signed-off-by: Artem Senichev --- src/pixmap.c | 30 ++++++++++++++++++++++++------ src/ui.c | 7 +++---- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/pixmap.c b/src/pixmap.c index 008df57..0aa2f1f 100644 --- a/src/pixmap.c +++ b/src/pixmap.c @@ -445,9 +445,13 @@ void pixmap_scale(enum pixmap_scale scaler, const struct pixmap* src, const long cpus = sysconf(_SC_NPROCESSORS_ONLN); #endif - const size_t threads_num = cpus > 0 ? min(16, cpus) : 1; - struct scale_task* tasks = malloc(threads_num * sizeof(struct scale_task)); - scale_fn fn = scaler == pixmap_nearest ? scale_nearest : scale_bicubic; + // background threads + const size_t threads_num = min(16, max(cpus, 1)) - 1; + struct scale_task* tasks = NULL; + + const scale_fn scaler_fn = + scaler == pixmap_nearest ? scale_nearest : scale_bicubic; + struct scale_param sp = { .src = src, .dst = dst, @@ -457,15 +461,29 @@ void pixmap_scale(enum pixmap_scale scaler, const struct pixmap* src, .alpha = alpha, }; + // create task for each CPU core + if (threads_num) { + tasks = malloc(threads_num * sizeof(struct scale_task)); + if (!tasks) { + return; + } + } + + // start background threads for (size_t i = 0; i < threads_num; ++i) { struct scale_task* task = &tasks[i]; + task->tid = 0; task->sp = &sp; - task->start = i; - task->step = threads_num; - task->fn = fn; + task->start = i + 1; // skip first line + task->step = threads_num + 1; + task->fn = scaler_fn; pthread_create(&task->tid, NULL, scale_thread, task); } + // execute the first task in the current thread + scaler_fn(&sp, 0, threads_num + 1); + + // wait for all threads to complete for (size_t i = 0; i < threads_num; ++i) { pthread_join(tasks[i].tid, NULL); } diff --git a/src/ui.c b/src/ui.c index 9f6b77b..b6e0f41 100644 --- a/src/ui.c +++ b/src/ui.c @@ -751,10 +751,9 @@ void ui_draw_commit(void) #ifdef TRACE_DRAW_TIME struct timespec curr; clock_gettime(CLOCK_MONOTONIC, &curr); - printf("%ld ms\n", - (curr.tv_sec * 1000 + curr.tv_nsec / 1000000) - - (ctx.wnd.draw_time.tv_sec * 1000 + - ctx.wnd.draw_time.tv_nsec / 1000000)); + const double ns = (curr.tv_sec * 1000000000 + curr.tv_nsec) - + (ctx.wnd.draw_time.tv_sec * 1000000000 + ctx.wnd.draw_time.tv_nsec); + printf("Rendered in %.6f sec\n", ns / 1000000000); #endif wl_surface_attach(ctx.wl.surface, ctx.wnd.current, 0, 0);