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, ®istry_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