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