• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <assert.h>
6 #include <memory.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <poll.h>
15 #include <sys/ioctl.h>
16 #include <sys/mman.h>
17 #include <sys/socket.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <syslog.h>
21 #include <unistd.h>
22 
23 #include "aura-shell.h"
24 #include "linux-dmabuf-unstable-v1.h"
25 #include "viewporter.h"
26 #include "xdg-shell.h"
27 #include "virtio-gpu-metadata-v1.h"
28 #include <wayland-client-core.h>
29 #include <wayland-client-protocol.h>
30 #include <wayland-client.h>
31 
32 // BTN_LEFT is copied from linux/input-event-codes.h because the kernel headers
33 // aren't readily available in some downstream projects.
34 #define BTN_LEFT 0x110
35 
36 #define DEFAULT_SCALE 2
37 #define MAX_BUFFER_COUNT 64
38 #define EVENT_BUF_SIZE 256
39 
40 const int32_t DWL_KEYBOARD_KEY_STATE_RELEASED = WL_KEYBOARD_KEY_STATE_RELEASED;
41 const int32_t DWL_KEYBOARD_KEY_STATE_PRESSED  = WL_KEYBOARD_KEY_STATE_PRESSED;
42 
43 const uint32_t DWL_EVENT_TYPE_KEYBOARD_ENTER = 0x00;
44 const uint32_t DWL_EVENT_TYPE_KEYBOARD_LEAVE = 0x01;
45 const uint32_t DWL_EVENT_TYPE_KEYBOARD_KEY   = 0x02;
46 const uint32_t DWL_EVENT_TYPE_POINTER_ENTER  = 0x10;
47 const uint32_t DWL_EVENT_TYPE_POINTER_LEAVE  = 0x11;
48 const uint32_t DWL_EVENT_TYPE_POINTER_MOVE   = 0x12;
49 const uint32_t DWL_EVENT_TYPE_POINTER_BUTTON = 0x13;
50 const uint32_t DWL_EVENT_TYPE_TOUCH_DOWN     = 0x20;
51 const uint32_t DWL_EVENT_TYPE_TOUCH_UP       = 0x21;
52 const uint32_t DWL_EVENT_TYPE_TOUCH_MOTION   = 0x22;
53 
54 const uint32_t DWL_SURFACE_FLAG_RECEIVE_INPUT = 1 << 0;
55 const uint32_t DWL_SURFACE_FLAG_HAS_ALPHA     = 1 << 1;
56 
57 struct dwl_event {
58 	const void *surface_descriptor;
59 	uint32_t event_type;
60 	int32_t params[3];
61 };
62 
63 struct dwl_context;
64 
65 struct interfaces {
66 	struct dwl_context *context;
67 	struct wl_compositor *compositor;
68 	struct wl_subcompositor *subcompositor;
69 	struct wl_shm *shm;
70 	struct wl_seat *seat;
71 	struct zaura_shell *aura; // optional
72 	struct zwp_linux_dmabuf_v1 *linux_dmabuf;
73 	struct xdg_wm_base *xdg_wm_base;
74 	struct wp_viewporter *viewporter; // optional
75 	struct wp_virtio_gpu_metadata_v1 *virtio_gpu_metadata; // optional
76 };
77 
78 struct output {
79 	struct wl_output *output;
80 	struct zaura_output *aura_output;
81 	struct dwl_context *context;
82 	uint32_t id;
83 	uint32_t current_scale;
84 	uint32_t device_scale_factor;
85 	bool internal;
86 };
87 
88 struct input {
89 	struct wl_keyboard *wl_keyboard;
90 	struct wl_pointer *wl_pointer;
91 	struct wl_surface *keyboard_input_surface;
92 	struct wl_surface *pointer_input_surface;
93 	int32_t pointer_x;
94 	int32_t pointer_y;
95 	bool pointer_lbutton_state;
96 };
97 
98 struct dwl_context {
99 	struct wl_display *display;
100 	struct dwl_surface *surfaces[MAX_BUFFER_COUNT];
101 	struct dwl_dmabuf *dmabufs[MAX_BUFFER_COUNT];
102 	struct interfaces ifaces;
103 	struct input input;
104 	bool output_added;
105 	struct output outputs[8];
106 
107 	struct dwl_event event_cbuf[EVENT_BUF_SIZE];
108 	size_t event_read_pos;
109 	size_t event_write_pos;
110 };
111 
112 #define outputs_for_each(context, pos, output)                                 \
113 	for (pos = 0, output = &context->outputs[pos];                         \
114 	     pos < (sizeof(context->outputs) / sizeof(context->outputs[0]));   \
115 	     pos++, output = &context->outputs[pos])
116 
117 struct dwl_dmabuf {
118 	uint32_t width;
119 	uint32_t height;
120 	uint32_t import_id;
121 	bool in_use;
122 	struct wl_buffer *buffer;
123 	struct dwl_context *context;
124 };
125 
126 struct dwl_surface {
127 	struct dwl_context *context;
128 	struct wl_surface *wl_surface;
129 	struct zaura_surface *aura;
130 	struct xdg_surface *xdg_surface;
131 	struct xdg_toplevel *xdg_toplevel;
132 	struct wp_viewport *viewport;
133 	struct wp_virtio_gpu_surface_metadata_v1 *virtio_gpu_surface_metadata;
134 	struct wl_subsurface *subsurface;
135 	uint32_t width;
136 	uint32_t height;
137 	uint32_t surface_id;
138 	double scale;
139 	bool close_requested;
140 	size_t buffer_count;
141 	uint64_t buffer_use_bit_mask;
142 	struct wl_buffer *buffers[0];
143 };
144 
145 static_assert(sizeof(((struct dwl_surface *)0)->buffer_use_bit_mask) * 8 >=
146 		  MAX_BUFFER_COUNT,
147 	      "not enough bits in buffer_use_bit_mask");
148 
output_geometry(void * data,struct wl_output * output,int x,int y,int physical_width,int physical_height,int subpixel,const char * make,const char * model,int transform)149 static void output_geometry(void *data, struct wl_output *output, int x, int y,
150 			    int physical_width, int physical_height,
151 			    int subpixel, const char *make, const char *model,
152 			    int transform)
153 {
154 	(void)data;
155 	(void)output;
156 	(void)x;
157 	(void)y;
158 	(void)physical_width;
159 	(void)physical_height;
160 	(void)subpixel;
161 	(void)make;
162 	(void)model;
163 	(void)transform;
164 }
165 
output_mode(void * data,struct wl_output * output,uint32_t flags,int width,int height,int refresh)166 static void output_mode(void *data, struct wl_output *output, uint32_t flags,
167 			int width, int height, int refresh)
168 {
169 	(void)data;
170 	(void)output;
171 	(void)flags;
172 	(void)width;
173 	(void)height;
174 	(void)refresh;
175 }
176 
output_done(void * data,struct wl_output * output)177 static void output_done(void *data, struct wl_output *output)
178 {
179 	(void)data;
180 	(void)output;
181 }
182 
output_scale(void * data,struct wl_output * wl_output,int32_t scale_factor)183 static void output_scale(void *data, struct wl_output *wl_output,
184 			 int32_t scale_factor)
185 {
186 	(void)wl_output;
187 	struct output *output = (struct output *)data;
188 	struct dwl_context *context = output->context;
189 
190 	// If the aura interface is available, we prefer the scale factor
191 	// reported by that.
192 	if (context->ifaces.aura)
193 		return;
194 
195 	output->current_scale = 1000 * scale_factor;
196 }
197 
198 static const struct wl_output_listener output_listener = {
199     .geometry = output_geometry,
200     .mode = output_mode,
201     .done = output_done,
202     .scale = output_scale};
203 
aura_output_scale(void * data,struct zaura_output * aura_output,uint32_t flags,uint32_t scale)204 static void aura_output_scale(void *data, struct zaura_output *aura_output,
205 			      uint32_t flags, uint32_t scale)
206 {
207 	(void)aura_output;
208 	struct output *output = (struct output *)data;
209 	if (flags & ZAURA_OUTPUT_SCALE_PROPERTY_CURRENT) {
210 		output->current_scale = scale;
211 	}
212 }
213 
aura_output_connection(void * data,struct zaura_output * aura_output,uint32_t connection)214 static void aura_output_connection(void *data, struct zaura_output *aura_output,
215 				   uint32_t connection)
216 {
217 	(void)aura_output;
218 	struct output *output = (struct output *)data;
219 	output->internal = connection == ZAURA_OUTPUT_CONNECTION_TYPE_INTERNAL;
220 }
221 
aura_output_device_scale_factor(void * data,struct zaura_output * aura_output,uint32_t device_scale_factor)222 static void aura_output_device_scale_factor(void *data,
223 					    struct zaura_output *aura_output,
224 					    uint32_t device_scale_factor)
225 {
226 	(void)aura_output;
227 	struct output *output = (struct output *)data;
228 	output->device_scale_factor = device_scale_factor;
229 }
230 
231 static const struct zaura_output_listener aura_output_listener = {
232     .scale = aura_output_scale,
233     .connection = aura_output_connection,
234     .device_scale_factor = aura_output_device_scale_factor};
235 
xdg_wm_base_ping(void * data,struct xdg_wm_base * xdg_wm_base,uint32_t serial)236 static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base,
237 			     uint32_t serial)
238 {
239 	(void)data;
240 	xdg_wm_base_pong(xdg_wm_base, serial);
241 }
242 
243 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
244 	.ping = xdg_wm_base_ping,
245 };
246 
247 
wl_keyboard_keymap(void * data,struct wl_keyboard * wl_keyboard,uint32_t format,int32_t fd,uint32_t size)248 static void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
249 			       uint32_t format, int32_t fd, uint32_t size)
250 {
251 	(void)data;
252 	(void)wl_keyboard;
253 	(void)fd;
254 	(void)size;
255 	if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
256 		syslog(LOG_ERR, "wl_keyboard: invalid keymap format");
257 	}
258 }
259 
dwl_context_push_event(struct dwl_context * self,struct dwl_event * event)260 static void dwl_context_push_event(struct dwl_context *self,
261 				   struct dwl_event *event)
262 {
263 	if (!self)
264 		return;
265 
266 	memcpy(self->event_cbuf + self->event_write_pos, event,
267 	       sizeof(struct dwl_event));
268 
269 	if (++self->event_write_pos == EVENT_BUF_SIZE)
270 		self->event_write_pos = 0;
271 }
272 
wl_keyboard_enter(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)273 static void wl_keyboard_enter(void *data, struct wl_keyboard *wl_keyboard,
274 			      uint32_t serial, struct wl_surface *surface,
275 			      struct wl_array *keys)
276 {
277 	(void)wl_keyboard;
278 	(void)serial;
279 	(void)surface;
280 	struct dwl_context *context = (struct dwl_context*)data;
281 	struct input *input = &context->input;
282 	uint32_t *key;
283 	struct dwl_event event = {0};
284 	input->keyboard_input_surface = surface;
285 	wl_array_for_each(key, keys) {
286 		event.surface_descriptor = input->keyboard_input_surface;
287 		event.event_type = DWL_EVENT_TYPE_KEYBOARD_KEY;
288 		event.params[0] = (int32_t)*key;
289 		event.params[1] = DWL_KEYBOARD_KEY_STATE_PRESSED;
290 		dwl_context_push_event(context, &event);
291 	}
292 }
293 
wl_keyboard_key(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)294 static void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
295 			    uint32_t serial, uint32_t time, uint32_t key,
296 			    uint32_t state)
297 {
298 	struct dwl_context *context = (struct dwl_context*)data;
299 	struct input *input = &context->input;
300 	(void)wl_keyboard;
301 	(void)serial;
302 	(void)time;
303 	struct dwl_event event = {0};
304 	event.surface_descriptor = input->keyboard_input_surface;
305 	event.event_type = DWL_EVENT_TYPE_KEYBOARD_KEY;
306 	event.params[0] = (int32_t)key;
307 	event.params[1] = state;
308 	dwl_context_push_event(context, &event);
309 }
310 
wl_keyboard_leave(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,struct wl_surface * surface)311 static void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard,
312 			      uint32_t serial, struct wl_surface *surface)
313 {
314 	struct dwl_context *context = (struct dwl_context*)data;
315 	struct input *input = &context->input;
316 	struct dwl_event event = {0};
317 	(void)wl_keyboard;
318 	(void)serial;
319 	(void)surface;
320 
321 	event.surface_descriptor = input->keyboard_input_surface;
322 	event.event_type = DWL_EVENT_TYPE_KEYBOARD_LEAVE;
323 	dwl_context_push_event(context, &event);
324 
325 	input->keyboard_input_surface = NULL;
326 }
327 
wl_keyboard_modifiers(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)328 static void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
329 				  uint32_t serial, uint32_t mods_depressed,
330 				  uint32_t mods_latched, uint32_t mods_locked,
331 				  uint32_t group)
332 {
333 	(void)data;
334 	(void)wl_keyboard;
335 	(void)serial;
336 	(void)mods_depressed;
337 	(void)mods_latched;
338 	(void)mods_locked;
339 	(void)group;
340 }
341 
wl_keyboard_repeat_info(void * data,struct wl_keyboard * wl_keyboard,int32_t rate,int32_t delay)342 static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
343 				    int32_t rate, int32_t delay)
344 {
345 	(void)data;
346 	(void)wl_keyboard;
347 	(void)rate;
348 	(void)delay;
349 }
350 
351 static const struct wl_keyboard_listener wl_keyboard_listener = {
352 	.keymap = wl_keyboard_keymap,
353 	.enter = wl_keyboard_enter,
354 	.leave = wl_keyboard_leave,
355 	.key = wl_keyboard_key,
356 	.modifiers = wl_keyboard_modifiers,
357 	.repeat_info = wl_keyboard_repeat_info,
358 };
359 
pointer_enter_handler(void * data,struct wl_pointer * wl_pointer,uint32_t serial,struct wl_surface * surface,wl_fixed_t x,wl_fixed_t y)360 static void pointer_enter_handler(void *data, struct wl_pointer *wl_pointer,
361 				  uint32_t serial, struct wl_surface *surface,
362 				  wl_fixed_t x, wl_fixed_t y)
363 {
364 	struct dwl_context *context = (struct dwl_context*)data;
365 	struct input *input = &context->input;
366 	(void)wl_pointer;
367 	(void)serial;
368 
369 	input->pointer_input_surface = surface;
370 	input->pointer_x = wl_fixed_to_int(x);
371 	input->pointer_y = wl_fixed_to_int(y);
372 }
373 
pointer_leave_handler(void * data,struct wl_pointer * wl_pointer,uint32_t serial,struct wl_surface * surface)374 static void pointer_leave_handler(void *data, struct wl_pointer *wl_pointer,
375 				  uint32_t serial, struct wl_surface *surface)
376 {
377 	struct dwl_context *context = (struct dwl_context*)data;
378 	struct input *input = &context->input;
379 	(void)wl_pointer;
380 	(void)serial;
381 	(void)surface;
382 
383 	input->pointer_input_surface = NULL;
384 }
385 
pointer_motion_handler(void * data,struct wl_pointer * wl_pointer,uint32_t time,wl_fixed_t x,wl_fixed_t y)386 static void pointer_motion_handler(void *data, struct wl_pointer *wl_pointer,
387 				   uint32_t time, wl_fixed_t x, wl_fixed_t y)
388 {
389 	struct dwl_context *context = (struct dwl_context*)data;
390 	struct input *input = &context->input;
391 	struct dwl_event event = {0};
392 	(void)wl_pointer;
393 	(void)time;
394 
395 	input->pointer_x = wl_fixed_to_int(x);
396 	input->pointer_y = wl_fixed_to_int(y);
397 	if (input->pointer_lbutton_state) {
398 		event.surface_descriptor = input->pointer_input_surface;
399 		event.event_type = DWL_EVENT_TYPE_TOUCH_MOTION;
400 		event.params[0] = input->pointer_x;
401 		event.params[1] = input->pointer_y;
402 		dwl_context_push_event(context, &event);
403 	}
404 }
405 
pointer_button_handler(void * data,struct wl_pointer * wl_pointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)406 static void pointer_button_handler(void *data, struct wl_pointer *wl_pointer,
407 				   uint32_t serial, uint32_t time, uint32_t button,
408 				   uint32_t state)
409 {
410 	struct dwl_context *context = (struct dwl_context*)data;
411 	struct input *input = &context->input;
412 	(void)wl_pointer;
413 	(void)time;
414 	(void)serial;
415 
416 	// we track only the left mouse button since we emulate a single touch device
417 	if (button == BTN_LEFT) {
418 		input->pointer_lbutton_state = state != 0;
419 		struct dwl_event event = {0};
420 		event.surface_descriptor = input->pointer_input_surface;
421 		event.event_type = (state != 0)?
422 			DWL_EVENT_TYPE_TOUCH_DOWN:DWL_EVENT_TYPE_TOUCH_UP;
423 		event.params[0] = input->pointer_x;
424 		event.params[1] = input->pointer_y;
425 		dwl_context_push_event(context, &event);
426 	}
427 }
428 
wl_pointer_frame(void * data,struct wl_pointer * wl_pointer)429 static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
430 {
431 	(void)data;
432 	(void)wl_pointer;
433 }
434 
pointer_axis_handler(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis,wl_fixed_t value)435 static void pointer_axis_handler(void *data, struct wl_pointer *wl_pointer,
436 				 uint32_t time, uint32_t axis, wl_fixed_t value)
437 {
438 	(void)data;
439 	(void)wl_pointer;
440 	(void)time;
441 	(void)axis;
442 	(void)value;
443 }
444 
wl_pointer_axis_source(void * data,struct wl_pointer * wl_pointer,uint32_t axis_source)445 static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer,
446 				   uint32_t axis_source)
447 {
448 	(void)data;
449 	(void)wl_pointer;
450 	(void)axis_source;
451 }
452 
wl_pointer_axis_stop(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis)453 static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
454 					uint32_t time, uint32_t axis)
455 {
456 	(void)data;
457 	(void)wl_pointer;
458 	(void)time;
459 	(void)axis;
460 }
461 
wl_pointer_axis_discrete(void * data,struct wl_pointer * wl_pointer,uint32_t axis,int32_t discrete)462 static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
463 				     uint32_t axis, int32_t discrete)
464 {
465 	(void)data;
466 	(void)wl_pointer;
467 	(void)axis;
468 	(void)discrete;
469 }
470 
471 const struct wl_pointer_listener wl_pointer_listener = {
472 	.enter = pointer_enter_handler,
473 	.leave = pointer_leave_handler,
474 	.motion = pointer_motion_handler,
475 	.button = pointer_button_handler,
476 	.axis = pointer_axis_handler,
477 	.frame = wl_pointer_frame,
478 	.axis_source = wl_pointer_axis_source,
479 	.axis_stop = wl_pointer_axis_stop,
480 	.axis_discrete = wl_pointer_axis_discrete,
481 };
482 
wl_seat_capabilities(void * data,struct wl_seat * wl_seat,uint32_t capabilities)483 static void wl_seat_capabilities(void *data, struct wl_seat *wl_seat,
484 				 uint32_t capabilities)
485 {
486 	struct dwl_context *context = (struct dwl_context*)data;
487 	struct input *input = &context->input;
488 	bool have_keyboard = capabilities & WL_SEAT_CAPABILITY_KEYBOARD;
489 	bool have_pointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
490 
491 	if (have_keyboard && input->wl_keyboard == NULL) {
492 		input->wl_keyboard = wl_seat_get_keyboard(wl_seat);
493 		wl_keyboard_add_listener(input->wl_keyboard, &wl_keyboard_listener, context);
494 	} else if (!have_keyboard && input->wl_keyboard != NULL) {
495 		wl_keyboard_release(input->wl_keyboard);
496 		input->wl_keyboard = NULL;
497 	}
498 
499 	if (have_pointer && input->wl_pointer == NULL) {
500 		input->wl_pointer = wl_seat_get_pointer(wl_seat);
501 		wl_pointer_add_listener(input->wl_pointer, &wl_pointer_listener, context);
502 	} else if (!have_pointer && input->wl_pointer != NULL) {
503 		wl_pointer_release(input->wl_pointer);
504 		input->wl_pointer = NULL;
505 	}
506 }
507 
wl_seat_name(void * data,struct wl_seat * wl_seat,const char * name)508 static void wl_seat_name(void *data, struct wl_seat *wl_seat, const char *name)
509 {
510 	(void)data;
511 	(void)wl_seat;
512 	(void)name;
513 }
514 
515 static const struct wl_seat_listener wl_seat_listener = {
516 	.capabilities = wl_seat_capabilities,
517 	.name = wl_seat_name,
518 };
519 
dwl_context_output_add(struct dwl_context * context,struct wl_output * wl_output,uint32_t id)520 static void dwl_context_output_add(struct dwl_context *context,
521 				   struct wl_output *wl_output, uint32_t id)
522 {
523 	size_t i;
524 	struct output *output;
525 	outputs_for_each(context, i, output)
526 	{
527 		if (output->output == NULL) {
528 			context->output_added = true;
529 			output->id = id;
530 			output->output = wl_output;
531 			output->context = context;
532 			output->current_scale = 1000;
533 			output->device_scale_factor = 1000;
534 			// This is a fun little hack from reveman. The idea is
535 			// that the first display will be internal and never get
536 			// removed.
537 			output->internal = i == 0;
538 			wl_output_add_listener(output->output, &output_listener,
539 					       output);
540 			return;
541 		}
542 	}
543 }
544 
dwl_context_output_remove_destroy(struct dwl_context * context,uint32_t id)545 static void dwl_context_output_remove_destroy(struct dwl_context *context,
546 					      uint32_t id)
547 {
548 	size_t i;
549 	struct output *output;
550 	outputs_for_each(context, i, output)
551 	{
552 		if (output->id == id) {
553 			if (output->aura_output)
554 				zaura_output_destroy(output->aura_output);
555 			wl_output_destroy(output->output);
556 			memset(output, 0, sizeof(struct output));
557 			return;
558 		}
559 	}
560 }
561 
dwl_context_output_get_aura(struct dwl_context * context)562 static void dwl_context_output_get_aura(struct dwl_context *context)
563 {
564 	if (!context->ifaces.aura)
565 		return;
566 
567 	size_t i;
568 	struct output *output;
569 	outputs_for_each(context, i, output)
570 	{
571 		if (output->output != NULL && output->aura_output == NULL) {
572 			output->aura_output = zaura_shell_get_aura_output(
573 			    context->ifaces.aura, output->output);
574 			zaura_output_add_listener(
575 			    output->aura_output, &aura_output_listener, output);
576 		}
577 	}
578 }
579 
registry_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)580 static void registry_global(void *data, struct wl_registry *registry,
581 			    uint32_t id, const char *interface,
582 			    uint32_t version)
583 {
584 	(void)version;
585 	struct interfaces *ifaces = (struct interfaces *)data;
586 	if (strcmp(interface, wl_compositor_interface.name) == 0) {
587 		ifaces->compositor = (struct wl_compositor *)wl_registry_bind(
588 		    registry, id, &wl_compositor_interface, 3);
589 	} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
590 		ifaces->subcompositor =
591 		    (struct wl_subcompositor *)wl_registry_bind(
592 			registry, id, &wl_subcompositor_interface, 1);
593 	} else if (strcmp(interface, wl_shm_interface.name) == 0) {
594 		ifaces->shm = (struct wl_shm *)wl_registry_bind(
595 		    registry, id, &wl_shm_interface, 1);
596 	} else if (strcmp(interface, wl_seat_interface.name) == 0) {
597 		ifaces->seat = (struct wl_seat *)wl_registry_bind(
598 		    registry, id, &wl_seat_interface, 5);
599 		wl_seat_add_listener(ifaces->seat, &wl_seat_listener, ifaces->context);
600 	} else if (strcmp(interface, wl_output_interface.name) == 0) {
601 		struct wl_output *output = (struct wl_output *)wl_registry_bind(
602 		    registry, id, &wl_output_interface, 2);
603 		dwl_context_output_add(ifaces->context, output, id);
604 	} else if (strcmp(interface, "zaura_shell") == 0 && version >= 6) {
605 		ifaces->aura = (struct zaura_shell *)wl_registry_bind(
606 		    registry, id, &zaura_shell_interface, 6);
607 	} else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
608 		ifaces->linux_dmabuf =
609 		    (struct zwp_linux_dmabuf_v1 *)wl_registry_bind(
610 			registry, id, &zwp_linux_dmabuf_v1_interface, 1);
611 	} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
612 		ifaces->xdg_wm_base = (struct xdg_wm_base *)wl_registry_bind(
613 		    registry, id, &xdg_wm_base_interface, 1);
614 		xdg_wm_base_add_listener(ifaces->xdg_wm_base, &xdg_wm_base_listener,
615 			NULL);
616 	} else if (strcmp(interface, "wp_viewporter") == 0) {
617 		ifaces->viewporter = (struct wp_viewporter *)wl_registry_bind(
618 		    registry, id, &wp_viewporter_interface, 1);
619 	} else if (strcmp(interface, "wp_virtio_gpu_metadata_v1") == 0) {
620 		ifaces->virtio_gpu_metadata =
621 			(struct wp_virtio_gpu_metadata_v1 *)wl_registry_bind(
622 			registry, id, &wp_virtio_gpu_metadata_v1_interface, 1);
623 	}
624 }
625 
global_remove(void * data,struct wl_registry * registry,uint32_t id)626 static void global_remove(void *data, struct wl_registry *registry, uint32_t id)
627 {
628 	(void)registry;
629 
630 	struct interfaces *ifaces = (struct interfaces *)data;
631 	// If the ID matches any output, this will remove it. Otherwise, this is
632 	// a no-op.
633 	dwl_context_output_remove_destroy(ifaces->context, id);
634 
635 	if (ifaces->aura &&
636 	    wl_proxy_get_id((struct wl_proxy *)ifaces->aura) == id) {
637 		zaura_shell_destroy(ifaces->aura);
638 		ifaces->aura = NULL;
639 	}
640 
641 	// TODO(zachr): deal with the removal of some of the required
642 	// interfaces.
643 }
644 
645 static const struct wl_registry_listener registry_listener = {
646     .global = registry_global, .global_remove = global_remove};
647 
toplevel_configure(void * data,struct xdg_toplevel * xdg_toplevel,int32_t width,int32_t height,struct wl_array * states)648 static void toplevel_configure(void *data,
649 			       struct xdg_toplevel *xdg_toplevel,
650 			       int32_t width, int32_t height,
651 			       struct wl_array *states)
652 {
653 	(void)data;
654 	(void)xdg_toplevel;
655 	(void)width;
656 	(void)height;
657 	(void)states;
658 }
659 
toplevel_close(void * data,struct xdg_toplevel * xdg_toplevel)660 static void toplevel_close(void *data,
661 			   struct xdg_toplevel *xdg_toplevel)
662 {
663 	(void)xdg_toplevel;
664 	struct dwl_surface *surface = (struct dwl_surface *)data;
665 	surface->close_requested = true;
666 }
667 
668 static const struct xdg_toplevel_listener toplevel_listener = {
669     .configure = toplevel_configure, .close = toplevel_close};
670 
xdg_surface_configure_handler(void * data,struct xdg_surface * xdg_surface,uint32_t serial)671 static void xdg_surface_configure_handler(void *data,
672 					  struct xdg_surface *xdg_surface,
673 					  uint32_t serial)
674 {
675 	(void)data;
676 	xdg_surface_ack_configure(xdg_surface, serial);
677 }
678 
679 static const struct xdg_surface_listener xdg_surface_listener = {
680 	.configure = xdg_surface_configure_handler
681 };
682 
surface_enter(void * data,struct wl_surface * wl_surface,struct wl_output * wl_output)683 static void surface_enter(void *data, struct wl_surface *wl_surface,
684 			  struct wl_output *wl_output)
685 {
686 	struct dwl_surface *surface = (struct dwl_surface *)data;
687 
688 	struct output *output =
689 	    (struct output *)wl_output_get_user_data(wl_output);
690 
691 	surface->scale = (output->device_scale_factor / 1000.0) *
692 			 (output->current_scale / 1000.0);
693 
694 	if (surface->viewport) {
695 		wp_viewport_set_destination(
696 		    surface->viewport, ceil(surface->width / surface->scale),
697 		    ceil(surface->height / surface->scale));
698 	} else {
699 		wl_surface_set_buffer_scale(wl_surface, surface->scale);
700 	}
701 
702 	wl_surface_commit(wl_surface);
703 }
704 
surface_leave(void * data,struct wl_surface * wl_surface,struct wl_output * output)705 static void surface_leave(void *data, struct wl_surface *wl_surface,
706 			  struct wl_output *output)
707 {
708 	(void)data;
709 	(void)wl_surface;
710 	(void)output;
711 }
712 
713 static const struct wl_surface_listener surface_listener = {
714     .enter = surface_enter, .leave = surface_leave};
715 
dwl_context_new()716 struct dwl_context *dwl_context_new()
717 {
718 	struct dwl_context *ctx = calloc(1, sizeof(struct dwl_context));
719 	ctx->ifaces.context = ctx;
720 	return ctx;
721 }
722 
dwl_context_destroy(struct dwl_context ** self)723 void dwl_context_destroy(struct dwl_context **self)
724 {
725 	if ((*self)->display)
726 		wl_display_disconnect((*self)->display);
727 	free(*self);
728 	*self = NULL;
729 }
730 
dwl_context_setup(struct dwl_context * self,const char * socket_path)731 bool dwl_context_setup(struct dwl_context *self, const char *socket_path)
732 {
733 	struct wl_display *display = wl_display_connect(socket_path);
734 	if (!display) {
735 		syslog(LOG_ERR, "failed to connect to display");
736 		return false;
737 	}
738 	self->display = display;
739 	wl_display_set_user_data(display, self);
740 
741 	struct wl_registry *registry = wl_display_get_registry(display);
742 	if (!registry) {
743 		syslog(LOG_ERR, "failed to get registry");
744 		goto fail;
745 	}
746 
747 	struct interfaces *ifaces = &self->ifaces;
748 	wl_registry_add_listener(registry, &registry_listener, ifaces);
749 	wl_display_roundtrip(display);
750 	dwl_context_output_get_aura(self);
751 
752 	if (!ifaces->shm) {
753 		syslog(LOG_ERR, "missing interface shm");
754 		goto fail;
755 	}
756 	if (!ifaces->compositor) {
757 		syslog(LOG_ERR, "missing interface compositor");
758 		goto fail;
759 	}
760 	if (!ifaces->subcompositor) {
761 		syslog(LOG_ERR, "missing interface subcompositor");
762 		goto fail;
763 	}
764 	if (!ifaces->seat) {
765 		syslog(LOG_ERR, "missing interface seat");
766 		goto fail;
767 	}
768 	if (!ifaces->linux_dmabuf) {
769 		syslog(LOG_ERR, "missing interface linux_dmabuf");
770 		goto fail;
771 	}
772 	if (!ifaces->xdg_wm_base) {
773 		syslog(LOG_ERR, "missing interface xdg_wm_base");
774 		goto fail;
775 	}
776 
777 	return true;
778 
779 fail:
780 	wl_display_disconnect(display);
781 	self->display = NULL;
782 	return false;
783 }
784 
dwl_context_fd(struct dwl_context * self)785 int dwl_context_fd(struct dwl_context *self)
786 {
787 	return wl_display_get_fd(self->display);
788 }
789 
dwl_context_dispatch(struct dwl_context * self)790 void dwl_context_dispatch(struct dwl_context *self)
791 {
792 	wl_display_dispatch(self->display);
793 	if (self->output_added) {
794 		self->output_added = false;
795 		dwl_context_output_get_aura(self);
796 		wl_display_roundtrip(self->display);
797 	}
798 }
799 
linux_buffer_created(void * data,struct zwp_linux_buffer_params_v1 * zwp_linux_buffer_params_v1,struct wl_buffer * buffer)800 static void linux_buffer_created(
801     void *data, struct zwp_linux_buffer_params_v1 *zwp_linux_buffer_params_v1,
802     struct wl_buffer *buffer)
803 {
804 	(void)zwp_linux_buffer_params_v1;
805 	struct dwl_dmabuf *dmabuf = (struct dwl_dmabuf *)data;
806 	dmabuf->buffer = buffer;
807 }
808 
linux_buffer_failed(void * data,struct zwp_linux_buffer_params_v1 * zwp_linux_buffer_params_v1)809 static void linux_buffer_failed(
810     void *data, struct zwp_linux_buffer_params_v1 *zwp_linux_buffer_params_v1)
811 {
812 	(void)data;
813 	(void)zwp_linux_buffer_params_v1;
814 }
815 
816 static const struct zwp_linux_buffer_params_v1_listener linux_buffer_listener =
817     {.created = linux_buffer_created, .failed = linux_buffer_failed};
818 
dmabuf_buffer_release(void * data,struct wl_buffer * buffer)819 static void dmabuf_buffer_release(void *data, struct wl_buffer *buffer)
820 {
821 	struct dwl_dmabuf *dmabuf = (struct dwl_dmabuf *)data;
822 	(void)buffer;
823 
824 	dmabuf->in_use = false;
825 }
826 
827 static const struct wl_buffer_listener dmabuf_buffer_listener = {
828     .release = dmabuf_buffer_release};
829 
dwl_context_add_dmabuf(struct dwl_context * self,struct dwl_dmabuf * dmabuf)830 static bool dwl_context_add_dmabuf(struct dwl_context *self,
831 				   struct dwl_dmabuf *dmabuf)
832 {
833 	size_t i;
834 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
835 		if (!self->dmabufs[i]) {
836 			self->dmabufs[i] = dmabuf;
837 			return true;
838 		}
839 	}
840 
841 	return false;
842 }
843 
dwl_context_remove_dmabuf(struct dwl_context * self,uint32_t import_id)844 static void dwl_context_remove_dmabuf(struct dwl_context *self,
845 				      uint32_t import_id)
846 {
847 	size_t i;
848 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
849 		if (self->dmabufs[i] &&
850 		    self->dmabufs[i]->import_id == import_id) {
851 			self->dmabufs[i] = NULL;
852 		}
853 	}
854 }
855 
dwl_context_get_dmabuf(struct dwl_context * self,uint32_t import_id)856 static struct dwl_dmabuf *dwl_context_get_dmabuf(struct dwl_context *self,
857 					         uint32_t import_id)
858 {
859 	size_t i;
860 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
861 		if (self->dmabufs[i] &&
862 		    self->dmabufs[i]->import_id == import_id) {
863 			return self->dmabufs[i];
864 		}
865 	}
866 
867 	return NULL;
868 }
869 
dwl_context_dmabuf_new(struct dwl_context * self,uint32_t import_id,int fd,uint32_t offset,uint32_t stride,uint64_t modifier,uint32_t width,uint32_t height,uint32_t fourcc)870 struct dwl_dmabuf *dwl_context_dmabuf_new(struct dwl_context *self,
871 					  uint32_t import_id,
872 					  int fd, uint32_t offset,
873 					  uint32_t stride, uint64_t modifier,
874 					  uint32_t width, uint32_t height,
875 					  uint32_t fourcc)
876 {
877 	struct dwl_dmabuf *dmabuf = calloc(1, sizeof(struct dwl_dmabuf));
878 	if (!dmabuf) {
879 		syslog(LOG_ERR, "failed to allocate dwl_dmabuf");
880 		return NULL;
881 	}
882 	dmabuf->width = width;
883 	dmabuf->height = height;
884 
885 	struct zwp_linux_buffer_params_v1 *params =
886 	    zwp_linux_dmabuf_v1_create_params(self->ifaces.linux_dmabuf);
887 	if (!params) {
888 		syslog(LOG_ERR,
889 		       "failed to allocate zwp_linux_buffer_params_v1");
890 		free(dmabuf);
891 		return NULL;
892 	}
893 
894 	zwp_linux_buffer_params_v1_add_listener(params, &linux_buffer_listener,
895 						dmabuf);
896 	zwp_linux_buffer_params_v1_add(params, fd, 0 /* plane_idx */, offset,
897 				       stride, modifier >> 32,
898 				       (uint32_t)modifier);
899 	zwp_linux_buffer_params_v1_create(params, width, height, fourcc, 0);
900 	wl_display_roundtrip(self->display);
901 	zwp_linux_buffer_params_v1_destroy(params);
902 
903 	if (!dmabuf->buffer) {
904 		syslog(LOG_ERR, "failed to get wl_buffer for dmabuf");
905 		free(dmabuf);
906 		return NULL;
907 	}
908 
909 	wl_buffer_add_listener(dmabuf->buffer, &dmabuf_buffer_listener, dmabuf);
910 
911 	dmabuf->import_id = import_id;
912 	dmabuf->context = self;
913 	if (!dwl_context_add_dmabuf(self, dmabuf)) {
914 		syslog(LOG_ERR, "failed to add dmabuf to context");
915 		free(dmabuf);
916 		return NULL;
917 	}
918 
919 	return dmabuf;
920 }
921 
dwl_dmabuf_destroy(struct dwl_dmabuf ** self)922 void dwl_dmabuf_destroy(struct dwl_dmabuf **self)
923 {
924 	dwl_context_remove_dmabuf((*self)->context, (*self)->import_id);
925 	wl_buffer_destroy((*self)->buffer);
926 	free(*self);
927 	*self = NULL;
928 }
929 
surface_buffer_release(void * data,struct wl_buffer * buffer)930 static void surface_buffer_release(void *data, struct wl_buffer *buffer)
931 {
932 	struct dwl_surface *surface = (struct dwl_surface *)data;
933 	(void)buffer;
934 
935 	size_t i;
936 	for (i = 0; i < surface->buffer_count; i++) {
937 		if (buffer == surface->buffers[i]) {
938 			surface->buffer_use_bit_mask &= ~(1 << i);
939 			break;
940 		}
941 	}
942 }
943 
944 static const struct wl_buffer_listener surface_buffer_listener = {
945     .release = surface_buffer_release};
946 
dwl_context_get_surface(struct dwl_context * self,uint32_t surface_id)947 static struct dwl_surface *dwl_context_get_surface(struct dwl_context *self,
948 					           uint32_t surface_id)
949 {
950 	size_t i;
951 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
952 		if (self->surfaces[i] &&
953 		    self->surfaces[i]->surface_id == surface_id) {
954 			return self->surfaces[i];
955 		}
956 	}
957 
958 	return NULL;
959 }
960 
dwl_context_add_surface(struct dwl_context * self,struct dwl_surface * surface)961 static bool dwl_context_add_surface(struct dwl_context *self,
962 				    struct dwl_surface *surface)
963 {
964 	size_t i;
965 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
966 		if (!self->surfaces[i]) {
967 			self->surfaces[i] = surface;
968 			return true;
969 		}
970 	}
971 
972 	return false;
973 }
974 
dwl_context_remove_surface(struct dwl_context * self,uint32_t surface_id)975 static void dwl_context_remove_surface(struct dwl_context *self,
976 				       uint32_t surface_id)
977 {
978 	size_t i;
979 	for (i = 0; i < MAX_BUFFER_COUNT; i++) {
980 		if (self->surfaces[i] &&
981 		    self->surfaces[i]->surface_id == surface_id) {
982 			self->surfaces[i] = NULL;
983 		}
984 	}
985 }
986 
dwl_context_surface_new(struct dwl_context * self,uint32_t parent_id,uint32_t surface_id,int shm_fd,size_t shm_size,size_t buffer_size,uint32_t width,uint32_t height,uint32_t stride,uint32_t flags)987 struct dwl_surface *dwl_context_surface_new(struct dwl_context *self,
988 					    uint32_t parent_id,
989 					    uint32_t  surface_id,
990 					    int shm_fd, size_t shm_size,
991 					    size_t buffer_size, uint32_t width,
992 					    uint32_t height, uint32_t stride,
993 					    uint32_t flags)
994 {
995 	if (buffer_size == 0)
996 		return NULL;
997 
998 	size_t buffer_count = shm_size / buffer_size;
999 	if (buffer_count == 0)
1000 		return NULL;
1001 	if (buffer_count > MAX_BUFFER_COUNT)
1002 		return NULL;
1003 
1004 	struct dwl_surface *disp_surface =
1005 	    calloc(1, sizeof(struct dwl_surface) +
1006 			  sizeof(struct wl_buffer *) * buffer_count);
1007 	if (!disp_surface)
1008 		return NULL;
1009 
1010 	disp_surface->context = self;
1011 	disp_surface->width = width;
1012 	disp_surface->height = height;
1013 	disp_surface->scale = DEFAULT_SCALE;
1014 	disp_surface->buffer_count = buffer_count;
1015 
1016 	struct wl_shm_pool *shm_pool =
1017 	    wl_shm_create_pool(self->ifaces.shm, shm_fd, shm_size);
1018 	if (!shm_pool) {
1019 		syslog(LOG_ERR, "failed to make shm pool");
1020 		goto fail;
1021 	}
1022 
1023 	size_t i;
1024 	uint32_t format = (flags & DWL_SURFACE_FLAG_HAS_ALPHA)?
1025 		WL_SHM_FORMAT_ARGB8888:WL_SHM_FORMAT_XRGB8888;
1026 
1027 	for (i = 0; i < buffer_count; i++) {
1028 		struct wl_buffer *buffer = wl_shm_pool_create_buffer(
1029 		    shm_pool, buffer_size * i, width, height, stride, format);
1030 		if (!buffer) {
1031 			syslog(LOG_ERR, "failed to create buffer");
1032 			goto fail;
1033 		}
1034 		disp_surface->buffers[i] = buffer;
1035 	}
1036 
1037 	for (i = 0; i < buffer_count; i++)
1038 		wl_buffer_add_listener(disp_surface->buffers[i],
1039 				       &surface_buffer_listener, disp_surface);
1040 
1041 	disp_surface->wl_surface =
1042 	    wl_compositor_create_surface(self->ifaces.compositor);
1043 	if (!disp_surface->wl_surface) {
1044 		syslog(LOG_ERR, "failed to make surface");
1045 		goto fail;
1046 	}
1047 
1048 	wl_surface_add_listener(disp_surface->wl_surface, &surface_listener,
1049 				disp_surface);
1050 
1051 	struct wl_region *region = wl_compositor_create_region(self->ifaces.compositor);
1052 	if (!region) {
1053 		syslog(LOG_ERR, "failed to make region");
1054 		goto fail;
1055 	}
1056 
1057 	bool receive_input = (flags & DWL_SURFACE_FLAG_RECEIVE_INPUT);
1058 	if (receive_input) {
1059 		wl_region_add(region, 0, 0, width, height);
1060 	} else {
1061 		// We have to add an empty region because NULL doesn't work
1062 		wl_region_add(region, 0, 0, 0, 0);
1063 	}
1064 	wl_surface_set_input_region(disp_surface->wl_surface, region);
1065 	wl_surface_set_opaque_region(disp_surface->wl_surface, region);
1066 	wl_region_destroy(region);
1067 
1068 	if (!parent_id) {
1069 		disp_surface->xdg_surface = xdg_wm_base_get_xdg_surface(
1070 		    self->ifaces.xdg_wm_base, disp_surface->wl_surface);
1071 		if (!disp_surface->xdg_surface) {
1072 			syslog(LOG_ERR, "failed to make xdg shell surface");
1073 			goto fail;
1074 		}
1075 
1076 		disp_surface->xdg_toplevel =
1077 		    xdg_surface_get_toplevel(disp_surface->xdg_surface);
1078 		if (!disp_surface->xdg_toplevel) {
1079 			syslog(LOG_ERR,
1080 			       "failed to make toplevel xdg shell surface");
1081 			goto fail;
1082 		}
1083 		xdg_toplevel_set_title(disp_surface->xdg_toplevel, "crosvm");
1084 		xdg_toplevel_add_listener(disp_surface->xdg_toplevel,
1085 					      &toplevel_listener, disp_surface);
1086 
1087 		xdg_surface_add_listener(disp_surface->xdg_surface,
1088 					     &xdg_surface_listener,
1089 					     NULL);
1090 		if (self->ifaces.aura) {
1091 			disp_surface->aura = zaura_shell_get_aura_surface(
1092 			    self->ifaces.aura, disp_surface->wl_surface);
1093 			if (!disp_surface->aura) {
1094 				syslog(LOG_ERR, "failed to make aura surface");
1095 				goto fail;
1096 			}
1097 			zaura_surface_set_frame(
1098 			    disp_surface->aura,
1099 			    ZAURA_SURFACE_FRAME_TYPE_NORMAL);
1100 		}
1101 
1102 		// signal that the surface is ready to be configured
1103 		wl_surface_commit(disp_surface->wl_surface);
1104 
1105 		// wait for the surface to be configured
1106 		wl_display_roundtrip(self->display);
1107 	} else {
1108 		struct dwl_surface *parent_surface =
1109 			dwl_context_get_surface(self, parent_id);
1110 
1111 		if (!parent_surface) {
1112 			syslog(LOG_ERR, "failed to find parent_surface");
1113 			goto fail;
1114 		}
1115 
1116 		disp_surface->subsurface = wl_subcompositor_get_subsurface(
1117 		    self->ifaces.subcompositor, disp_surface->wl_surface,
1118 		    parent_surface->wl_surface);
1119 		if (!disp_surface->subsurface) {
1120 			syslog(LOG_ERR, "failed to make subsurface");
1121 			goto fail;
1122 		}
1123 		wl_subsurface_set_desync(disp_surface->subsurface);
1124 	}
1125 
1126 	if (self->ifaces.viewporter) {
1127 		disp_surface->viewport = wp_viewporter_get_viewport(
1128 		    self->ifaces.viewporter, disp_surface->wl_surface);
1129 		if (!disp_surface->viewport) {
1130 			syslog(LOG_ERR, "failed to make surface viewport");
1131 			goto fail;
1132 		}
1133 	}
1134 
1135 	if (self->ifaces.virtio_gpu_metadata) {
1136 		disp_surface->virtio_gpu_surface_metadata =
1137 			wp_virtio_gpu_metadata_v1_get_surface_metadata(
1138 				self->ifaces.virtio_gpu_metadata, disp_surface->wl_surface);
1139 		if (!disp_surface->virtio_gpu_surface_metadata) {
1140 			syslog(LOG_ERR, "failed to make surface virtio surface metadata");
1141 			goto fail;
1142 		}
1143 	}
1144 
1145 	wl_surface_attach(disp_surface->wl_surface, disp_surface->buffers[0], 0,
1146 			  0);
1147 	wl_surface_damage(disp_surface->wl_surface, 0, 0, width, height);
1148 	wl_shm_pool_destroy(shm_pool);
1149 
1150 	// Needed to get outputs before iterating them.
1151 	wl_display_roundtrip(self->display);
1152 
1153 	// Assuming that this surface will enter the internal output initially,
1154 	// trigger a surface enter for that output before doing the first
1155 	// surface commit. THis is to avoid unpleasant artifacts when the
1156 	// surface first appears.
1157 	struct output *output;
1158 	outputs_for_each(self, i, output)
1159 	{
1160 		if (output->internal) {
1161 			surface_enter(disp_surface, disp_surface->wl_surface,
1162 				      output->output);
1163 		}
1164 	}
1165 
1166 	wl_surface_commit(disp_surface->wl_surface);
1167 	wl_display_flush(self->display);
1168 
1169 	disp_surface->surface_id = surface_id;
1170 	if (!dwl_context_add_surface(self, disp_surface)) {
1171 		syslog(LOG_ERR, "failed to add surface to context");
1172 		goto fail;
1173 	}
1174 
1175 	return disp_surface;
1176 fail:
1177 	if (disp_surface->virtio_gpu_surface_metadata)
1178 		wp_virtio_gpu_surface_metadata_v1_destroy(
1179 			disp_surface->virtio_gpu_surface_metadata);
1180 	if (disp_surface->viewport)
1181 		wp_viewport_destroy(disp_surface->viewport);
1182 	if (disp_surface->subsurface)
1183 		wl_subsurface_destroy(disp_surface->subsurface);
1184 	if (disp_surface->xdg_toplevel)
1185 		xdg_toplevel_destroy(disp_surface->xdg_toplevel);
1186 	if (disp_surface->xdg_surface)
1187 		xdg_surface_destroy(disp_surface->xdg_surface);
1188 	if (disp_surface->aura)
1189 		zaura_surface_destroy(disp_surface->aura);
1190 	if (disp_surface->wl_surface)
1191 		wl_surface_destroy(disp_surface->wl_surface);
1192 	for (i = 0; i < buffer_count; i++)
1193 		if (disp_surface->buffers[i])
1194 			wl_buffer_destroy(disp_surface->buffers[i]);
1195 	if (shm_pool)
1196 		wl_shm_pool_destroy(shm_pool);
1197 	free(disp_surface);
1198 	return NULL;
1199 }
1200 
dwl_surface_destroy(struct dwl_surface ** self)1201 void dwl_surface_destroy(struct dwl_surface **self)
1202 {
1203 	size_t i;
1204 
1205 	dwl_context_remove_surface((*self)->context, (*self)->surface_id);
1206 	if ((*self)->virtio_gpu_surface_metadata)
1207 		wp_virtio_gpu_surface_metadata_v1_destroy(
1208 			(*self)->virtio_gpu_surface_metadata);
1209 	if ((*self)->viewport)
1210 		wp_viewport_destroy((*self)->viewport);
1211 	if ((*self)->subsurface)
1212 		wl_subsurface_destroy((*self)->subsurface);
1213 	if ((*self)->xdg_toplevel)
1214 		xdg_toplevel_destroy((*self)->xdg_toplevel);
1215 	if ((*self)->xdg_surface)
1216 		xdg_surface_destroy((*self)->xdg_surface);
1217 	if ((*self)->aura)
1218 		zaura_surface_destroy((*self)->aura);
1219 	if ((*self)->wl_surface)
1220 		wl_surface_destroy((*self)->wl_surface);
1221 	for (i = 0; i < (*self)->buffer_count; i++)
1222 		wl_buffer_destroy((*self)->buffers[i]);
1223 	wl_display_flush((*self)->context->display);
1224 	free(*self);
1225 	*self = NULL;
1226 }
1227 
dwl_surface_commit(struct dwl_surface * self)1228 void dwl_surface_commit(struct dwl_surface *self)
1229 {
1230 	// It is possible that we are committing frames faster than the
1231 	// compositor can put them on the screen. This may result in dropped
1232 	// frames, but this is acceptable considering there is no good way to
1233 	// apply back pressure to the guest gpu driver right now. The intention
1234 	// of this module is to help bootstrap gpu support, so it does not have
1235 	// to have artifact free rendering.
1236 	wl_surface_commit(self->wl_surface);
1237 	wl_display_flush(self->context->display);
1238 }
1239 
dwl_surface_buffer_in_use(struct dwl_surface * self,size_t buffer_index)1240 bool dwl_surface_buffer_in_use(struct dwl_surface *self, size_t buffer_index)
1241 {
1242 	return (self->buffer_use_bit_mask & (1 << buffer_index)) != 0;
1243 }
1244 
dwl_surface_flip(struct dwl_surface * self,size_t buffer_index)1245 void dwl_surface_flip(struct dwl_surface *self, size_t buffer_index)
1246 {
1247 	if (buffer_index >= self->buffer_count)
1248 		return;
1249 	wl_surface_attach(self->wl_surface, self->buffers[buffer_index], 0, 0);
1250 	wl_surface_damage(self->wl_surface, 0, 0, self->width, self->height);
1251 	dwl_surface_commit(self);
1252 	self->buffer_use_bit_mask |= 1 << buffer_index;
1253 }
1254 
dwl_surface_flip_to(struct dwl_surface * self,uint32_t import_id)1255 void dwl_surface_flip_to(struct dwl_surface *self, uint32_t import_id)
1256 {
1257 	// Surface and dmabuf have to exist in same context.
1258 	struct dwl_dmabuf *dmabuf = dwl_context_get_dmabuf(self->context,
1259 							   import_id);
1260 	if (!dmabuf)
1261 		return;
1262 
1263 	if (self->width != dmabuf->width || self->height != dmabuf->height)
1264 		return;
1265 	wl_surface_attach(self->wl_surface, dmabuf->buffer, 0, 0);
1266 	wl_surface_damage(self->wl_surface, 0, 0, self->width, self->height);
1267 	dwl_surface_commit(self);
1268 	dmabuf->in_use = true;
1269 }
1270 
dwl_surface_close_requested(const struct dwl_surface * self)1271 bool dwl_surface_close_requested(const struct dwl_surface *self)
1272 {
1273 	return self->close_requested;
1274 }
1275 
dwl_surface_set_position(struct dwl_surface * self,uint32_t x,uint32_t y)1276 void dwl_surface_set_position(struct dwl_surface *self, uint32_t x, uint32_t y)
1277 {
1278 	if (self->subsurface) {
1279 		wl_subsurface_set_position(self->subsurface, x / self->scale,
1280 					   y / self->scale);
1281 		wl_surface_commit(self->wl_surface);
1282 		wl_display_flush(self->context->display);
1283 	}
1284 }
1285 
dwl_surface_descriptor(const struct dwl_surface * self)1286 const void* dwl_surface_descriptor(const struct dwl_surface *self)
1287 {
1288 	return self->wl_surface;
1289 }
1290 
dwl_context_pending_events(const struct dwl_context * self)1291 bool dwl_context_pending_events(const struct dwl_context *self)
1292 {
1293 	if (self->event_write_pos == self->event_read_pos)
1294 		return false;
1295 
1296 	return true;
1297 }
1298 
dwl_context_next_event(struct dwl_context * self,struct dwl_event * event)1299 void dwl_context_next_event(struct dwl_context *self, struct dwl_event *event)
1300 {
1301 	memcpy(event, self->event_cbuf + self->event_read_pos,
1302 	       sizeof(struct dwl_event));
1303 
1304 	if (++self->event_read_pos == EVENT_BUF_SIZE)
1305 		self->event_read_pos = 0;
1306 }
1307 
dwl_surface_set_scanout_id(struct dwl_surface * self,uint32_t scanout_id)1308 void dwl_surface_set_scanout_id(struct dwl_surface *self, uint32_t scanout_id)
1309 {
1310 	if (self->virtio_gpu_surface_metadata) {
1311 		wp_virtio_gpu_surface_metadata_v1_set_scanout_id(
1312 			self->virtio_gpu_surface_metadata, scanout_id);
1313 	}
1314 }
1315