summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/output.c16
-rw-r--r--src/render.c124
-rw-r--r--src/render.h5
-rw-r--r--src/surface.c24
-rw-r--r--src/surface.h3
-rw-r--r--src/wlclock.c12
-rw-r--r--src/wlclock.h2
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;