diff options
author | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-26 12:53:19 +0200 |
---|---|---|
committer | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-26 13:04:26 +0200 |
commit | 24e8ee33b509f71bbcaaffe83bd49eb144c2c1a7 (patch) | |
tree | 3906c5890d3ff9493e3bae1581c7c4fc2b6895cd | |
parent | 4a1859161d80530ba62d970f4afab2c10876e3bc (diff) | |
download | wlclock-24e8ee33b509f71bbcaaffe83bd49eb144c2c1a7.tar.gz wlclock-24e8ee33b509f71bbcaaffe83bd49eb144c2c1a7.tar.bz2 |
Render on callback
-rw-r--r-- | src/output.c | 16 | ||||
-rw-r--r-- | src/render.c | 124 | ||||
-rw-r--r-- | src/render.h | 5 | ||||
-rw-r--r-- | src/surface.c | 24 | ||||
-rw-r--r-- | src/surface.h | 3 | ||||
-rw-r--r-- | src/wlclock.c | 12 | ||||
-rw-r--r-- | src/wlclock.h | 2 |
7 files changed, 140 insertions, 46 deletions
diff --git a/src/output.c b/src/output.c index 102d510..a6980ae 100644 --- a/src/output.c +++ b/src/output.c @@ -34,9 +34,14 @@ static void output_update_surface (struct Wlclock_output *output) if ( ! output->configured || output->name == NULL ) return; - struct Wlclock *clock = output->clock; - if ( clock->output == NULL || ! strcmp(clock->output, output->name) ) - create_surface(output); + if ( output->surface == NULL ) + { + struct Wlclock *clock = output->clock; + if ( clock->output == NULL || ! strcmp(clock->output, output->name) ) + create_surface(output); + } + else + update_surface(output->surface); } static void output_handle_done (void *data, struct wl_output *wl_output) @@ -47,10 +52,7 @@ static void output_handle_done (void *data, struct wl_output *wl_output) struct Wlclock_output *output = (struct Wlclock_output *)data; clocklog(output->clock, 1, "[output] Atomic update complete: global_name=%d\n", output->global_name); - if ( output->surface != NULL ) - update_surface(output->surface); - else - output_update_surface(output); + output_update_surface(output); } static const struct wl_output_listener output_listener = { diff --git a/src/render.c b/src/render.c index f58a4bd..de30ccd 100644 --- a/src/render.c +++ b/src/render.c @@ -58,7 +58,7 @@ static void draw_background (cairo_t *cairo, struct Wlclock_dimensions *dimensio if ( radius_bottom_right > center_size / 2 ) radius_bottom_right = center_size / 2; - clocklog(clock, 2, "[render] Render dimensions: size=%d cx=%d cy=%d w=%d h=%d\n", + clocklog(clock, 3, "[render] Render dimensions (scaled): size=%d cx=%d cy=%d w=%d h=%d\n", center_size, center_x, center_y, w, h); cairo_save(cairo); @@ -119,9 +119,10 @@ static void draw_clock_face (cairo_t *cairo, struct Wlclock_dimensions *dimensio if ( clock->face_line_size == 0 ) return; + /* Radii are choosen to roughly mimic xclock. */ double cx = scale * (dimensions->center_x + (dimensions->center_size / 2)); double cy = scale * (dimensions->center_y + (dimensions->center_size / 2)); - double or = scale * 0.9 * dimensions->center_size / 2; /* Radii mimick xclock. */ + double or = scale * 0.9 * dimensions->center_size / 2; double ir = scale * 0.85 * dimensions->center_size / 2; double bir = scale * 0.8 * dimensions->center_size / 2; double phi, phi_step = 2 * PI / 60; @@ -144,11 +145,14 @@ static void draw_clock_face (cairo_t *cairo, struct Wlclock_dimensions *dimensio static void draw_clock_hands (cairo_t *cairo, int32_t size, int32_t scale, struct Wlclock *clock) { + /* Radii are choosen to roughly mimic xclock. */ double cxy = scale * size / 2; - double mr = scale * 0.6 * size / 2; /* Radii mimick xclock. */ + double mr = scale * 0.6 * size / 2; double hr = scale * 0.4 * size / 2; double ir = scale * 0.075 * size / 2; - struct tm tm = *localtime(&clock->now); + + time_t now = time(NULL); + struct tm tm = *localtime(&now); double phi_min_step = 2 * PI / 60; double phi_min = phi_min_step * (tm.tm_min + 45); @@ -206,54 +210,130 @@ static void clear_buffer (cairo_t *cairo) cairo_restore(cairo); } -void render_background_frame (struct Wlclock_surface *surface) +static void render_background_frame (struct Wlclock_surface *surface) { struct Wlclock_output *output = surface->output; struct Wlclock *clock = output->clock; uint32_t scale = output->scale; + clocklog(clock, 2, "[render] Render background frame: global_name=%d\n", output->global_name); - /* Get new/next buffer. */ - if (! next_buffer(&surface->current_background_buffer, clock->shm, - surface->background_buffers, - surface->dimensions.w * scale, - surface->dimensions.h * scale)) - return; - cairo_t *cairo = surface->current_background_buffer->cairo; clear_buffer(cairo); draw_background(cairo, &surface->dimensions, scale, clock); draw_clock_face(cairo, &surface->dimensions, scale, clock); - wl_surface_set_buffer_scale(surface->background_surface, scale); - wl_surface_attach(surface->background_surface, surface->current_background_buffer->buffer, 0, 0); wl_surface_damage_buffer(surface->background_surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_attach(surface->background_surface, surface->current_background_buffer->buffer, 0, 0); + + surface->background_dirty = false; } -void render_hands_frame (struct Wlclock_surface *surface) +static void render_hands_frame (struct Wlclock_surface *surface) { struct Wlclock_output *output = surface->output; struct Wlclock *clock = output->clock; uint32_t scale = output->scale; + clocklog(clock, 2, "[render] Render hands frame: global_name=%d\n", output->global_name); - /* Get new/next buffer. */ + cairo_t *cairo = surface->current_hands_buffer->cairo; + clear_buffer(cairo); + + draw_clock_hands(cairo, surface->dimensions.center_size, scale, clock); + + wl_surface_damage_buffer(surface->hands_surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_attach(surface->hands_surface, surface->current_hands_buffer->buffer, 0, 0); + + surface->hands_dirty = false; +} + +void make_background_dirty (struct Wlclock_surface *surface) +{ + if (surface->background_dirty) + return; + + struct Wlclock_output *output = surface->output; + struct Wlclock *clock = output->clock; + uint32_t scale = output->scale; + + clocklog(clock, 2, "[render] Making background dirty: global_name=%d\n", + output->global_name); + + if (! next_buffer(&surface->current_background_buffer, clock->shm, + surface->background_buffers, + surface->dimensions.w * scale, + surface->dimensions.h * scale)) + return; + surface->current_background_buffer->busy = true; + wl_surface_set_buffer_scale(surface->background_surface, scale); + wl_surface_attach(surface->background_surface, surface->current_background_buffer->buffer, 0, 0); + + surface->background_dirty = true; +} + +void make_hands_dirty (struct Wlclock_surface *surface) +{ + if (surface->hands_dirty) + return; + + struct Wlclock_output *output = surface->output; + struct Wlclock *clock = output->clock; + uint32_t scale = output->scale; + + clocklog(clock, 2, "[render] Making hands dirty: global_name=%d\n", + output->global_name); + if (! next_buffer(&surface->current_hands_buffer, clock->shm, surface->hands_buffers, surface->dimensions.center_size * scale, surface->dimensions.center_size * scale)) return; + surface->current_hands_buffer->busy = true; + wl_surface_set_buffer_scale(surface->hands_surface, scale); + wl_surface_attach(surface->hands_surface, surface->current_hands_buffer->buffer, 0, 0); - cairo_t *cairo = surface->current_hands_buffer->cairo; - clear_buffer(cairo); + surface->hands_dirty = true; +} - draw_clock_hands(cairo, surface->dimensions.center_size, scale, clock); +static void frame_handle_done (void *data, struct wl_callback *callback, uint32_t time) +{ + struct Wlclock_surface *surface = (struct Wlclock_surface *)data; + wl_callback_destroy(surface->frame_callback); + surface->frame_callback = NULL; + clocklog(surface->output->clock, 2, "[render] Frame callback: " + "global-name=%d background=%d hands=%d.\n", + surface->output->global_name, + surface->background_dirty, surface->hands_dirty); + if (surface->background_dirty) + render_background_frame(surface); + if (surface->hands_dirty) + render_hands_frame(surface); + wl_surface_commit(surface->hands_surface); + wl_surface_commit(surface->background_surface); +} - wl_surface_set_buffer_scale(surface->hands_surface, scale); - wl_surface_attach(surface->hands_surface, surface->current_hands_buffer->buffer, 0, 0); - wl_surface_damage_buffer(surface->hands_surface, 0, 0, INT32_MAX, INT32_MAX); +static const struct wl_callback_listener frame_callback_listener = { + .done = frame_handle_done +}; + +void schedule_frame (struct Wlclock_surface *surface, bool background, bool hands) +{ + if (! surface->configured) + return; + clocklog(surface->output->clock, 2, "[render] Scheduling frame: " + "global-name=%d background=%d hands=%d\n", + surface->output->global_name, background, hands); + if (background) + make_background_dirty(surface); + if (hands) + make_hands_dirty(surface); + if ( surface->frame_callback != NULL ) + return; + surface->frame_callback = wl_surface_frame(surface->background_surface); + wl_callback_add_listener(surface->frame_callback, &frame_callback_listener, surface); } diff --git a/src/render.h b/src/render.h index ed82de9..c942a7d 100644 --- a/src/render.h +++ b/src/render.h @@ -1,9 +1,10 @@ #ifndef WLCLOCK_RENDER_H #define WLCLOCK_RENDER_H +#include<stdbool.h> + struct Wlclock_surface; -void render_background_frame (struct Wlclock_surface *surface); -void render_hands_frame (struct Wlclock_surface *surface); +void schedule_frame (struct Wlclock_surface *surface, bool background, bool hands); #endif diff --git a/src/surface.c b/src/surface.c index 18e6131..63b56b3 100644 --- a/src/surface.c +++ b/src/surface.c @@ -3,6 +3,7 @@ #include<stdbool.h> #include<unistd.h> #include<string.h> +#include<time.h> #include<cairo/cairo.h> #include<wayland-server.h> @@ -42,6 +43,7 @@ static void layer_surface_handle_configure (void *data, if ( surface->dimensions.center_size < 10 ) surface->dimensions.center_size = 10; } + surface->configured = true; update_surface(surface); } @@ -131,6 +133,9 @@ bool create_surface (struct Wlclock_output *output) surface->hands_surface = NULL; surface->layer_surface = NULL; surface->configured = false; + surface->frame_callback = NULL; + surface->background_dirty = false; + surface->hands_dirty = false; if ( NULL == (surface->background_surface = wl_compositor_create_surface(clock->compositor)) ) { @@ -145,6 +150,8 @@ bool create_surface (struct Wlclock_output *output) clocklog(NULL, 0, "ERROR: Compositor did not create layer_surface.\n"); return false; } + zwlr_layer_surface_v1_add_listener(surface->layer_surface, + &layer_surface_listener, surface); if ( NULL == (surface->hands_surface = wl_compositor_create_surface(clock->compositor)) ) { @@ -161,11 +168,9 @@ bool create_surface (struct Wlclock_output *output) configure_layer_surface(surface); configure_subsurface(surface); - zwlr_layer_surface_v1_add_listener(surface->layer_surface, - &layer_surface_listener, surface); - wl_surface_commit(surface->background_surface); - wl_surface_commit(surface->hands_surface); + wl_surface_commit(surface->hands_surface); + wl_surface_commit(surface->background_surface); return true; } @@ -173,6 +178,8 @@ void destroy_surface (struct Wlclock_surface *surface) { if ( surface == NULL ) return; + if ( surface->output != NULL ) + surface->output->surface = NULL; if ( surface->layer_surface != NULL ) zwlr_layer_surface_v1_destroy(surface->layer_surface); if ( surface->subsurface != NULL ) @@ -181,6 +188,8 @@ void destroy_surface (struct Wlclock_surface *surface) wl_surface_destroy(surface->background_surface); if ( surface->hands_surface != NULL ) wl_surface_destroy(surface->hands_surface); + if ( surface->frame_callback != NULL ) + wl_callback_destroy(surface->frame_callback); finish_buffer(&surface->background_buffers[0]); finish_buffer(&surface->background_buffers[1]); finish_buffer(&surface->hands_buffers[0]); @@ -203,10 +212,9 @@ void update_surface (struct Wlclock_surface *surface) return; configure_layer_surface(surface); configure_subsurface(surface); - render_background_frame(surface); - render_hands_frame(surface); - wl_surface_commit(surface->background_surface); + schedule_frame(surface, true, true); wl_surface_commit(surface->hands_surface); + wl_surface_commit(surface->background_surface); } void update_all_surfaces (struct Wlclock *clock) @@ -225,7 +233,7 @@ void update_all_hands (struct Wlclock *clock) wl_list_for_each_safe(op, tmp, &clock->outputs, link) if ( op->surface != NULL ) { - render_hands_frame(op->surface); + schedule_frame(op->surface, false, true); wl_surface_commit(op->surface->hands_surface); wl_surface_commit(op->surface->background_surface); } diff --git a/src/surface.h b/src/surface.h index d2dcb25..7262a42 100644 --- a/src/surface.h +++ b/src/surface.h @@ -26,6 +26,9 @@ struct Wlclock_surface struct Wlclock_buffer hands_buffers[2]; struct Wlclock_buffer *current_hands_buffer; bool configured; + + struct wl_callback *frame_callback; + bool background_dirty, hands_dirty; }; bool create_surface (struct Wlclock_output *output); diff --git a/src/wlclock.c b/src/wlclock.c index 47154b8..89b6e5f 100644 --- a/src/wlclock.c +++ b/src/wlclock.c @@ -500,9 +500,10 @@ static bool handle_command_flags (struct Wlclock *clock, int argc, char *argv[]) return true; } -static time_t get_timeout (time_t now) +/* Timeout until next minute. */ +static time_t get_timeout (void) { - /* Timeout until the next minute. */ + time_t now = time(NULL); return ((now / 60 * 60 ) + 60 - now) * 1000; } @@ -511,6 +512,9 @@ static void clock_run (struct Wlclock *clock) clocklog(clock, 1, "[main] Starting loop.\n"); clock->ret = EXIT_SUCCESS; + // TODO simpler event loop, other signal handling + // while ( wl_display_dispatch(clock->display) != -1 ); + struct pollfd fds[2] = { 0 }; size_t wayland_fd = 0; size_t signal_fd = 1; @@ -556,12 +560,10 @@ static void clock_run (struct Wlclock *clock) } } while ( errno == EAGAIN ); - clock->now = time(NULL); - int ret = poll(fds, 2, get_timeout(clock->now)); + int ret = poll(fds, 2, get_timeout()); if ( ret == 0 ) { - clock->now = time(NULL); update_all_hands(clock); continue; } diff --git a/src/wlclock.h b/src/wlclock.h index 8f75233..a2dd9ce 100644 --- a/src/wlclock.h +++ b/src/wlclock.h @@ -40,8 +40,6 @@ struct Wlclock struct wl_list outputs; char *output; - time_t now; - bool loop; int verbosity; int ret; |