7 #include <wayland-server.h>
9 #include <libds/backend.h>
10 #include <libds/allocator/shm.h>
11 #include <libds/backend/wayland.h>
12 #include <libds/swapchain.h>
13 #include <libds/compositor.h>
20 struct ds_backend *backend;
21 struct ds_output *output;
22 struct ds_allocator *allocator;
23 struct ds_swapchain *swapchain;
24 struct ds_buffer *front_buffer;
26 struct wl_display *display;
29 struct wl_listener output_destroy;
30 struct wl_listener output_frame;
36 struct server _server;
38 static void init_server(struct server *server, struct wl_display *display);
39 static void fini_server(struct server *server);
40 static void output_handle_destroy(struct wl_listener *listener, void *data);
41 static void output_handle_frame(struct wl_listener *listener, void *data);
42 static void draw_output(struct server *server);
47 struct server *server = &_server;
48 struct wl_display *display;
50 ds_log_init(DS_DBG, NULL);
52 display = wl_display_create();
55 server->width = WIDTH;
56 server->height = HEIGHT;
58 init_server(server, display);
60 server->listener.output_destroy.notify = output_handle_destroy;
61 ds_output_add_destroy_listener(server->output,
62 &server->listener.output_destroy);
64 server->listener.output_frame.notify = output_handle_frame;
65 ds_output_add_frame_listener(server->output,
66 &server->listener.output_frame);
68 ds_backend_start(server->backend);
72 wl_display_run(server->display);
75 wl_display_destroy(display);
79 static struct ds_backend *
80 create_backend_auto(struct wl_display *display)
82 struct ds_backend *backend = NULL;
86 for (i = 0; i < 5; i++) {
87 snprintf(name, sizeof name, "wayland-%d", i);
88 backend = ds_wl_backend_create(display, name);
97 init_server(struct server *server, struct wl_display *display)
99 server->display = display;
101 server->backend = create_backend_auto(display);
102 assert(server->backend);
104 server->allocator = ds_shm_allocator_create();
105 assert(server->allocator);
107 server->swapchain = ds_swapchain_create(server->allocator,
108 server->width, server->height, WL_SHM_FORMAT_XRGB8888);
109 assert(server->swapchain);
112 ds_wl_backend_create_output(server->backend);
113 assert(server->output);
117 fini_server(struct server *server)
119 ds_buffer_unlock(server->front_buffer);
120 ds_swapchain_destroy(server->swapchain);
121 ds_allocator_destroy(server->allocator);
125 paint_pixels(void *image, int padding, int width, int height, uint32_t time)
127 const int halfh = padding + (height - padding * 2) / 2;
128 const int halfw = padding + (width - padding * 2) / 2;
130 uint32_t *pixel = image;
133 /* squared radii thresholds */
134 or = (halfw < halfh ? halfw : halfh) - 8;
139 pixel += padding * width;
140 for (y = padding; y < height - padding; y++) {
142 int y2 = (y - halfh) * (y - halfh);
145 for (x = padding; x < width - padding; x++) {
148 /* squared distance from center */
149 int r2 = (x - halfw) * (x - halfw) + y2;
152 v = (r2 / 32 + time / 64) * 0x0080401;
154 v = (y + time / 32) * 0x0080401;
156 v = (x + time / 16) * 0x0080401;
159 /* cross if compositor uses X from XRGB as alpha */
160 if (abs(x - y) > 6 && abs(x + y - height) > 6)
170 static inline int64_t
171 timespec_to_msec(const struct timespec *a)
173 return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
177 output_handle_destroy(struct wl_listener *listener,
178 void *data __attribute__((unused)))
180 struct server *server =
181 wl_container_of(listener, server, listener.output_destroy);
182 wl_display_terminate(server->display);
186 output_handle_frame(struct wl_listener *listener,
187 void *data __attribute__((unused)))
189 struct server *server =
190 wl_container_of(listener, server, listener.output_frame);
195 draw_output(struct server *server)
197 struct ds_buffer *buffer;
202 uint32_t frame_time_msec;
204 ds_dbg("Redraw output");
206 clock_gettime(CLOCK_MONOTONIC, &now);
207 frame_time_msec = timespec_to_msec(&now);
209 buffer = ds_swapchain_acquire(server->swapchain, NULL);
212 assert(ds_buffer_begin_data_ptr_access(buffer,
213 0, &data, &format, &stride) == true);
215 paint_pixels(data, 20, server->width, server->height, frame_time_msec);
217 ds_buffer_end_data_ptr_access(buffer);
219 ds_output_attach_buffer(server->output, buffer);
220 ds_output_commit(server->output);
222 if (server->front_buffer)
223 ds_buffer_unlock(server->front_buffer);
225 server->front_buffer = buffer;