mandelbrot-wl

mandelbrot-wl.git
git clone git://git.lenczewski.org/mandelbrot-wl.git
Log | Files | Refs

wayland-mandelbrot.c (11930B)


      1 #include "wayland-mandelbrot.h"
      2 #include "mandelbrot.h"
      3 
      4 static bool should_close = false;
      5 
      6 #define WIDTH 512
      7 #define HEIGHT 512
      8 #define ITERS 255
      9 
     10 #define PIXEL_ARGB8888_BUFFER_SIZE WIDTH * HEIGHT * sizeof(pixel_argb8888_t)
     11 
     12 static const struct viewrect view = {
     13 	.x0 = -2.0,
     14 	.y0 = -1.5,
     15 	.x1 = +1.2,
     16 	.y1 = +1.5,
     17 };
     18 
     19 static const struct drawrect draw = {
     20 	.width = WIDTH,
     21 	.height = HEIGHT,
     22 	.maxiters = ITERS,
     23 	.x0 = 0,
     24 	.y0 = 0,
     25 	.x1 = WIDTH - 1,
     26 	.y1 = HEIGHT - 1,
     27 };
     28 
     29 static pixel_p8_t pix[WIDTH * HEIGHT];
     30 
     31 static pixel_argb8888_t pal[UINT8_MAX];
     32 
     33 static void
     34 init_palette() {
     35 	for (size_t i = 0; i < UINT8_MAX; i++) {
     36 		if (i < ITERS) {
     37 			u8 v = scaleu8((f32)i / (f32)ITERS, 0x0, 0xff);
     38 			pal[i] = pixel_argb8888(0xff, v, v, v);
     39 		} else {
     40 			pal[i] = pixel_argb8888(0xff, 0, 0, 0);
     41 		}
     42 	}
     43 }
     44 
     45 static struct xkb_context *xkb_context = NULL;
     46 static struct xkb_keymap *xkb_keymap = NULL;
     47 static struct xkb_state *xkb_state = NULL;
     48 
     49 static struct wl_compositor *compositor = NULL;
     50 static struct wl_seat *seat = NULL;
     51 static struct wl_shm *shm = NULL;
     52 static struct wl_shm_pool *shm_pool = NULL;
     53 static struct wl_buffer *buffer = NULL;
     54 
     55 static struct wl_surface *surface = NULL;
     56 
     57 static struct wl_surface *cursor_surface = NULL;
     58 static struct wl_cursor_image *cursor_image = NULL;
     59 
     60 static struct wl_pointer *pointer = NULL;
     61 static struct wl_keyboard *keyboard = NULL;
     62 
     63 static struct xdg_wm_base *xdg_wm_base = NULL;
     64 static struct xdg_surface *xdg_surface = NULL;
     65 static struct xdg_toplevel *xdg_toplevel = NULL;
     66 
     67 static void
     68 wl_registry_global_handler(void *data, struct wl_registry *registry, u32 name, char const *interface, u32 version) {
     69 	(void) data;
     70 
     71 	printf("Interface: '%s', version: %u, name: %u\n", interface, version, name);
     72 
     73 	if (strcmp(interface, "wl_compositor") == 0) {
     74 		compositor = wl_registry_bind(registry, name, &wl_compositor_interface, version);
     75 	} else if (strcmp(interface, "wl_seat") == 0) {
     76 		seat = wl_registry_bind(registry, name, &wl_seat_interface, version);
     77 	} else if (strcmp(interface, "wl_shm") == 0) {
     78 		shm = wl_registry_bind(registry, name, &wl_shm_interface, version);
     79 	} else if (strcmp(interface, "xdg_wm_base") == 0) {
     80 		xdg_wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, version);
     81 	}
     82 }
     83 
     84 static void
     85 wl_registry_global_remove_handler(void *data, struct wl_registry *registry, u32 name) {
     86 	(void) data;
     87 	(void) registry;
     88 
     89 	printf("Removed: %u\n", name);
     90 }
     91 
     92 static const struct wl_registry_listener registry_listener = {
     93 	.global = wl_registry_global_handler,
     94 	.global_remove = wl_registry_global_remove_handler,
     95 };
     96 
     97 static void
     98 wl_pointer_enter_handler(void *data, struct wl_pointer *pointer, u32 serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) {
     99 	(void) data;
    100 	(void) surface;
    101 	(void) x;
    102 	(void) y;
    103 
    104 	wl_pointer_set_cursor(pointer, serial, cursor_surface, cursor_image->hotspot_x, cursor_image->hotspot_y);
    105 }
    106 
    107 static void
    108 wl_pointer_leave_handler(void *data, struct wl_pointer *pointer, u32 serial, struct wl_surface *surface) {
    109 	(void) data;
    110 	(void) pointer;
    111 	(void) serial;
    112 	(void) surface;
    113 }
    114 
    115 static void
    116 wl_pointer_motion_handler(void *data, struct wl_pointer *pointer, u32 time, wl_fixed_t x, wl_fixed_t y) {
    117 	(void) data;
    118 	(void) pointer;
    119 	(void) time;
    120 	(void) x;
    121 	(void) y;
    122 }
    123 
    124 static void
    125 wl_pointer_button_handler(void *data, struct wl_pointer *pointer, u32 serial, u32 time, u32 button, u32 state) {
    126 	(void) data;
    127 	(void) pointer;
    128 	(void) serial;
    129 	(void) time;
    130 
    131 	printf("button: %" PRIu32 ", state: %" PRIu32"\n", button, state);
    132 }
    133 
    134 static void
    135 wl_pointer_axis_handler(void *data, struct wl_pointer *pointer, u32 time, u32 axis, wl_fixed_t value) {
    136 	(void) data;
    137 	(void) pointer;
    138 	(void) time;
    139 	(void) axis;
    140 	(void) value;
    141 }
    142 
    143 static void
    144 wl_pointer_frame_handler(void *data, struct wl_pointer *pointer) {
    145 	(void) data;
    146 	(void) pointer;
    147 }
    148 
    149 static void
    150 wl_pointer_axis_source_handler(void *data, struct wl_pointer *pointer, u32 axis_source) {
    151 	(void) data;
    152 	(void) pointer;
    153 	(void) axis_source;
    154 }
    155 
    156 static void
    157 wl_pointer_axis_stop_handler(void *data, struct wl_pointer *pointer, u32 time, u32 axis) {
    158 	(void) data;
    159 	(void) pointer;
    160 	(void) time;
    161 	(void) axis;
    162 }
    163 
    164 static void
    165 wl_pointer_axis_discrete_handler(void *data, struct wl_pointer *pointer, u32 axis, wl_fixed_t discrete) {
    166 	(void) data;
    167 	(void) pointer;
    168 	(void) axis;
    169 	(void) discrete;
    170 }
    171 
    172 static void
    173 wl_pointer_axis_value120_handler(void *data, struct wl_pointer *pointer, u32 axis, wl_fixed_t discrete) {
    174 	(void) data;
    175 	(void) pointer;
    176 	(void) axis;
    177 	(void) discrete;
    178 }
    179 
    180 static void
    181 wl_pointer_axis_relative_direction_handler(void *data, struct wl_pointer *pointer, u32 axis, u32 direction) {
    182 	(void) data;
    183 	(void) pointer;
    184 	(void) axis;
    185 	(void) direction;
    186 }
    187 
    188 static const struct wl_pointer_listener wl_pointer_listener = {
    189 	.enter = wl_pointer_enter_handler,
    190 	.leave = wl_pointer_leave_handler,
    191 	.motion = wl_pointer_motion_handler,
    192 	.button = wl_pointer_button_handler,
    193 	.axis = wl_pointer_axis_handler,
    194 	.frame = wl_pointer_frame_handler,
    195 	.axis_source = wl_pointer_axis_source_handler,
    196 	.axis_stop = wl_pointer_axis_stop_handler,
    197 	.axis_discrete = wl_pointer_axis_discrete_handler,
    198 	.axis_value120 = wl_pointer_axis_value120_handler,
    199 	.axis_relative_direction = wl_pointer_axis_relative_direction_handler,
    200 };
    201 
    202 static void
    203 wl_keyboard_keymap_handler(void *data, struct wl_keyboard *keyboard, u32 format, wl_fixed_t fd, u32 size) {
    204 	(void) data;
    205 	(void) keyboard;
    206 
    207 	assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
    208 
    209 	char *map_shm = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
    210 	assert(map_shm != MAP_FAILED);
    211 
    212 	xkb_keymap = xkb_keymap_new_from_string(xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
    213 	xkb_state = xkb_state_new(xkb_keymap);
    214 
    215 	munmap(map_shm, size);
    216 	close(fd);
    217 }
    218 
    219 static void
    220 wl_keyboard_enter_handler(void *data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface, struct wl_array *keys) {
    221 	(void) data;
    222 	(void) keyboard;
    223 	(void) serial;
    224 	(void) surface;
    225 	(void) keys;
    226 }
    227 
    228 static void
    229 wl_keyboard_leave_handler(void *data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface) {
    230 	(void) data;
    231 	(void) keyboard;
    232 	(void) serial;
    233 	(void) surface;
    234 }
    235 
    236 static void
    237 wl_keyboard_key_handler(void *data, struct wl_keyboard *keyboard, u32 serial, u32 time, u32 key, u32 state) {
    238 	(void) data;
    239 	(void) keyboard;
    240 	(void) serial;
    241 	(void) time;
    242 
    243 	xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, key + 8);
    244 
    245 	char sym_name[128];
    246 	xkb_keysym_get_name(sym, sym_name, sizeof sym_name);
    247 
    248 	printf("key: %" PRIu32 ", state: %" PRIu32", sym: %" PRIu32 " (%s)\n", key, state, sym, sym_name);
    249 
    250 	if (sym == XKB_KEY_Escape) {
    251 		printf("Pressed the 'Escape' key\n");
    252 		should_close = true;
    253 	}
    254 }
    255 
    256 static void
    257 wl_keyboard_modifiers_handler(void *data, struct wl_keyboard *keyboard, u32 serial, u32 mods_depressed, u32 mods_latched, u32 mods_locked, u32 group) {
    258 	(void) data;
    259 	(void) keyboard;
    260 	(void) serial;
    261 	(void) mods_depressed;
    262 	(void) mods_latched;
    263 	(void) mods_locked;
    264 	(void) group;
    265 }
    266 
    267 static void
    268 wl_keyboard_repeat_info_handler(void *data, struct wl_keyboard *keyboard, wl_fixed_t rate, wl_fixed_t delay) {
    269 	(void) data;
    270 	(void) keyboard;
    271 	(void) rate;
    272 	(void) delay;
    273 }
    274 
    275 static const struct wl_keyboard_listener wl_keyboard_listener = {
    276 	.keymap = wl_keyboard_keymap_handler,
    277 	.enter = wl_keyboard_enter_handler,
    278 	.leave = wl_keyboard_leave_handler,
    279 	.key = wl_keyboard_key_handler,
    280 	.modifiers = wl_keyboard_modifiers_handler,
    281 	.repeat_info = wl_keyboard_repeat_info_handler,
    282 };
    283 
    284 static void
    285 xdg_wm_base_ping_handler(void *data, struct xdg_wm_base *wm_base, u32 serial) {
    286 	(void) data;
    287 
    288 	xdg_wm_base_pong(wm_base, serial);
    289 }
    290 
    291 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
    292 	.ping = xdg_wm_base_ping_handler,
    293 };
    294 
    295 static void
    296 xdg_surface_configure_handler(void *data, struct xdg_surface *surface, u32 serial) {
    297 	(void) data;
    298 
    299 	xdg_surface_ack_configure(surface, serial);
    300 }
    301 
    302 static const struct xdg_surface_listener xdg_surface_listener = {
    303 	.configure = xdg_surface_configure_handler,
    304 };
    305 
    306 static void
    307 xdg_toplevel_configure_handler(void *data, struct xdg_toplevel *toplevel, s32 width, s32 height, struct wl_array *states) {
    308 	(void) data;
    309 	(void) toplevel;
    310 	(void) width;
    311 	(void) height;
    312 	(void) states;
    313 }
    314 
    315 static void
    316 xdg_toplevel_close_handler(void *data, struct xdg_toplevel *toplevel) {
    317 	(void) data;
    318 	(void) toplevel;
    319 
    320 	should_close = true;
    321 }
    322 
    323 static void
    324 xdg_toplevel_configure_bounds_handler(void *data, struct xdg_toplevel *toplevel, s32 width, s32 height) {
    325 	(void) data;
    326 	(void) toplevel;
    327 	(void) width;
    328 	(void) height;
    329 }
    330 
    331 static void
    332 xdg_toplevel_wm_capabilities_handler(void *data, struct xdg_toplevel *toplevel, struct wl_array *capabilities) {
    333 	(void) data;
    334 	(void) toplevel;
    335 	(void) capabilities;
    336 }
    337 
    338 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
    339 	.configure = xdg_toplevel_configure_handler,
    340 	.close = xdg_toplevel_close_handler,
    341 	.configure_bounds = xdg_toplevel_configure_bounds_handler,
    342 	.wm_capabilities = xdg_toplevel_wm_capabilities_handler,
    343 };
    344 
    345 s32
    346 main(s32 argc, char **argv) {
    347 	(void) argc;
    348 	(void) argv;
    349 
    350 	init_palette();
    351 
    352 	printf("Initialised palette!\n");
    353 
    354 	mandelbrot_render(view, draw, pix);
    355 
    356 	printf("Rendered mandelbrot set!\n");
    357 
    358 	xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    359 
    360 	struct wl_display *display = wl_display_connect(NULL);
    361 	if (!display) {
    362 		fprintf(stderr, "Failed to connect to wayland display!\n");
    363 		return 1;
    364 	}
    365 
    366 	printf("Connected to wayland display!\n");
    367 
    368 	struct wl_registry *registry = wl_display_get_registry(display);
    369 	wl_registry_add_listener(registry, &registry_listener, NULL);
    370 
    371 	wl_display_roundtrip(display);
    372 
    373 	if (!compositor || !seat || !shm || !xdg_wm_base) {
    374 		fprintf(stderr, "Failed to bind required wayland registry globals!\n");
    375 		return 1;
    376 	}
    377 
    378 	pointer = wl_seat_get_pointer(seat);
    379 	wl_pointer_add_listener(pointer, &wl_pointer_listener, NULL);
    380 
    381 	keyboard = wl_seat_get_keyboard(seat);
    382 	wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, NULL);
    383 
    384 	xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
    385 
    386 	surface = wl_compositor_create_surface(compositor);
    387 
    388 	xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, surface);
    389 	xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL);
    390 
    391 	xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
    392 	xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
    393 	xdg_toplevel_set_title(xdg_toplevel, "mandelbrot-wl");
    394 
    395 	wl_surface_commit(surface);
    396 
    397 	size_t stride = WIDTH * sizeof(pixel_argb8888_t);
    398 	size_t size = PIXEL_ARGB8888_BUFFER_SIZE;
    399 
    400 	int mempool_fd = memfd_create("buffer", 0);
    401 	ftruncate(mempool_fd, size);
    402 
    403 	u8 *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, mempool_fd, 0);
    404 	(void) data;
    405 
    406 	shm_pool = wl_shm_create_pool(shm, mempool_fd, size);
    407 	if (!shm_pool) {
    408 		fprintf(stderr, "Failed to create shared memory pool of size %zu!\n", size);
    409 		return 1;
    410 	}
    411 
    412 	buffer = wl_shm_pool_create_buffer(shm_pool, 0, WIDTH, HEIGHT, stride, WL_SHM_FORMAT_ARGB8888);
    413 	if (!buffer) {
    414 		fprintf(stderr, "Failed to create buffer!\n");
    415 		return 1;
    416 	}
    417 
    418 	u32 *out = (u32 *)data;
    419 	for (size_t j = 0; j < HEIGHT; j++) {
    420 		for (size_t i = 0; i < WIDTH; i++) {
    421 			*out++ = pal[pix[(j * WIDTH) + i]];
    422 		}
    423 	}
    424 
    425 	struct wl_cursor_theme *cursor_theme = wl_cursor_theme_load(NULL, 24, shm);
    426 	struct wl_cursor *cursor = wl_cursor_theme_get_cursor(cursor_theme, "left_ptr");
    427 	cursor_image = cursor->images[0];
    428 	struct wl_buffer *cursor_buffer = wl_cursor_image_get_buffer(cursor_image);
    429 
    430 	cursor_surface = wl_compositor_create_surface(compositor);
    431 
    432 	wl_display_roundtrip(display);
    433 
    434 	wl_surface_attach(surface, buffer, 0, 0);
    435 	wl_surface_commit(surface);
    436 
    437 	wl_surface_attach(cursor_surface, cursor_buffer, 0, 0);
    438 	wl_surface_commit(cursor_surface);
    439 
    440 	do {
    441 		wl_display_dispatch(display);
    442 	} while (!should_close);
    443 
    444 	wl_display_disconnect(display);
    445 
    446 	printf("Disconnected from wayland display!\n");
    447 
    448 	return 0;
    449 }