db5a69228610a60d04be5071a3ff677cb00109fb
[AGL/meta-agl-devel.git] / meta-uhmi / meta-rvgpu / recipes-graphics / remote-virtio-gpu / remote-virtio-gpu / 0002-Add-agl-shell-desktop-and-xdg-shell-support.patch
1 From b60e0a361d29723643fe81b47bff8f86d5200258 Mon Sep 17 00:00:00 2001
2 From: Kenta <murakami.kenta002@jp.panasonic.com>
3 Date: Wed, 6 Sep 2023 18:44:22 +0900
4 Subject: [PATCH] Add agl-shell-desktop and xdg-shell supports
5
6 ---
7  CMakeLists.txt                              |  25 +++
8  include/rvgpu-renderer/renderer/rvgpu-egl.h |   9 +-
9  src/rvgpu-renderer/CMakeLists.txt           |   3 +
10  src/rvgpu-renderer/backend/rvgpu-gbm.c      |   2 +
11  src/rvgpu-renderer/backend/rvgpu-wayland.c  | 192 +++++++++++++++++---
12  src/rvgpu-renderer/renderer/rvgpu-egl.c     |   3 +
13  src/rvgpu-renderer/rvgpu-renderer.c         |  11 +-
14  7 files changed, 220 insertions(+), 25 deletions(-)
15
16 diff --git a/CMakeLists.txt b/CMakeLists.txt
17 index f569ca2..85c875a 100644
18 --- a/CMakeLists.txt
19 +++ b/CMakeLists.txt
20 @@ -20,6 +20,31 @@ cmake_minimum_required(VERSION 3.2)
21  project(rvgpu C)
22  set(CMAKE_C_STANDARD 11)
23  
24 +find_program(WAYLAND_SCANNER_EXECUTABLE wayland-scanner)
25 +
26 +message("generating agl-shell-desktop client files from: agl-shell-desktop.xml")
27 +
28 +execute_process ( COMMAND mkdir ${CMAKE_BINARY_DIR}/protocol)
29 +
30 +execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code
31 +  ${CMAKE_SYSROOT}/usr/share/agl-compositor/protocols/agl-shell-desktop.xml
32 +       ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.c)
33 +
34 +execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header
35 +  ${CMAKE_SYSROOT}/usr/share/agl-compositor/protocols/agl-shell-desktop.xml
36 +       ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.h)
37 +
38 +message("generating agl-shell-desktop client files from: xdg-shell.xml")
39 +
40 +execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code
41 +  ${CMAKE_SYSROOT}/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml
42 +       ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.c)
43 +
44 +execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header
45 +  ${CMAKE_SYSROOT}/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml
46 +       ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.h)
47 +
48 +
49  if (CMAKE_SYSROOT AND NOT ENV{PKG_CONFIG_LIBDIR})
50         set(ENV{PKG_CONFIG_DIR} "")
51         set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
52 diff --git a/include/rvgpu-renderer/renderer/rvgpu-egl.h b/include/rvgpu-renderer/renderer/rvgpu-egl.h
53 index ebd2bd2..dcff36a 100644
54 --- a/include/rvgpu-renderer/renderer/rvgpu-egl.h
55 +++ b/include/rvgpu-renderer/renderer/rvgpu-egl.h
56 @@ -59,6 +59,9 @@ struct rvgpu_scanout_params {
57         uint32_t id; /**< ID for scanout window (i.e. IVI id)*/
58         bool enabled; /**< enable/disable scanout */
59         bool boxed; /**< box is set by user */
60 +  struct rvgpu_box agl_win; /** Window position & limit on AGL */
61 +       bool agl_win_set;
62 +
63  };
64  
65  struct rvgpu_scanout {
66 @@ -118,6 +121,8 @@ struct rvgpu_egl_state {
67         bool spawn_support;
68  
69         bool use_scissors;
70 +
71 +  bool user_specified_scanouts;
72  };
73  
74  /** Initialize main context */
75 @@ -150,11 +155,11 @@ void rvgpu_egl_destroy_scanout(struct rvgpu_egl_state *e,
76  
77  /** Draw Virgl output on the surface */
78  void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
79 -                   bool vsync);
80 +           bool vsync);
81  
82  /** Redraw all scanouts with given resource id */
83  void rvgpu_egl_drawall(struct rvgpu_egl_state *e, unsigned int res_id,
84 -                      bool vsync);
85 +           bool vsync);
86  
87  /* Async event handling */
88  /** Call before polling */
89 diff --git a/src/rvgpu-renderer/CMakeLists.txt b/src/rvgpu-renderer/CMakeLists.txt
90 index dc5f5b0..c8a8c34 100644
91 --- a/src/rvgpu-renderer/CMakeLists.txt
92 +++ b/src/rvgpu-renderer/CMakeLists.txt
93 @@ -17,6 +17,8 @@
94  
95  
96  add_executable(rvgpu-renderer
97 +  ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.c
98 +       ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.c
99         backend/rvgpu-wayland.c
100         backend/rvgpu-gbm.c
101         renderer/rvgpu-egl.c
102 @@ -28,6 +30,7 @@ add_executable(rvgpu-renderer
103  target_include_directories(rvgpu-renderer
104         PRIVATE
105                 ${PROJECT_SOURCE_DIR}/include
106 +    ${CMAKE_BINARY_DIR}/protocol
107                 ${extlibs_INCLUDE_DIRS}
108         )
109  target_compile_definitions(rvgpu-renderer PRIVATE _GNU_SOURCE)
110 diff --git a/src/rvgpu-renderer/backend/rvgpu-gbm.c b/src/rvgpu-renderer/backend/rvgpu-gbm.c
111 index 4194b0d..b2b3ed3 100644
112 --- a/src/rvgpu-renderer/backend/rvgpu-gbm.c
113 +++ b/src/rvgpu-renderer/backend/rvgpu-gbm.c
114 @@ -259,6 +259,8 @@ static void rvgpu_gbm_create_scanout(struct rvgpu_egl_state *e,
115  
116         eglMakeCurrent(e->dpy, s->surface, s->surface, e->context);
117         glGenFramebuffers(1, &s->fb);
118 +
119 +  rvgpu_egl_draw(e, s, false);
120  }
121  
122  static void rvgpu_gbm_page_flip_handler(int fd, unsigned int sequence,
123 diff --git a/src/rvgpu-renderer/backend/rvgpu-wayland.c b/src/rvgpu-renderer/backend/rvgpu-wayland.c
124 index 0aaeaa7..c00ff00 100644
125 --- a/src/rvgpu-renderer/backend/rvgpu-wayland.c
126 +++ b/src/rvgpu-renderer/backend/rvgpu-wayland.c
127 @@ -39,12 +39,18 @@
128  #include <rvgpu-renderer/renderer/rvgpu-egl.h>
129  #include <rvgpu-renderer/renderer/rvgpu-input.h>
130  
131 +#include "agl-shell-desktop-protocol.h"
132 +#include "xdg-shell-protocol.h"
133 +
134  struct rvgpu_native {
135         /* Window structures */
136         struct wl_surface *surface;
137         struct wl_shell_surface *shell_surface;
138         struct wl_egl_window *egl_window;
139         struct ivi_surface *ivi_surface;
140 +  struct xdg_surface *xdg_surface;
141 +       struct xdg_toplevel *xdg_toplevel;
142 +       bool wait_for_configure;
143  };
144  
145  struct rvgpu_wl_state {
146 @@ -58,6 +64,9 @@ struct rvgpu_wl_state {
147         struct wl_keyboard *keyboard;
148         struct wl_shell *shell;
149         struct ivi_application *ivi_app;
150 +  struct xdg_wm_base *wm_base;
151 +       struct agl_shell_desktop *agl_shell_desktop;
152 +       struct wl_output *output;
153  
154         /* EGL structures */
155         struct rvgpu_egl_state egl;
156 @@ -78,6 +87,16 @@ static inline struct rvgpu_wl_state *to_wl(struct rvgpu_egl_state *e)
157         return rvgpu_container_of(e, struct rvgpu_wl_state, egl);
158  }
159  
160 +static void xdg_wm_base_ping(void *data, struct xdg_wm_base *shell,
161 +                               uint32_t serial)
162 +{
163 +        xdg_wm_base_pong(shell, serial);
164 +}
165 +
166 +static const struct xdg_wm_base_listener xdg_wm_base_listener = {
167 +        xdg_wm_base_ping,
168 +};
169 +
170  static struct wl_seat_listener seat_listener;
171  
172  static void registry_add_object(void *data, struct wl_registry *registry,
173 @@ -98,8 +117,17 @@ static void registry_add_object(void *data, struct wl_registry *registry,
174                         wl_registry_bind(registry, name, &wl_seat_interface, 1);
175                 wl_seat_add_listener(r->seat, &seat_listener, r);
176         } else if (!strcmp(interface, "ivi_application")) {
177 -               r->ivi_app = wl_registry_bind(registry, name,
178 -                                             &ivi_application_interface, 1);
179 +               r->ivi_app = wl_registry_bind(registry, name, &ivi_application_interface, 1);
180 +       } else if (strcmp(interface, "xdg_wm_base") == 0) {
181 +               r->wm_base = wl_registry_bind(registry, name,
182 +                        &xdg_wm_base_interface, 1);
183 +               xdg_wm_base_add_listener(r->wm_base, &xdg_wm_base_listener, r);
184 +       } else if (strcmp(interface, "agl_shell_desktop") == 0) {
185 +               r->agl_shell_desktop = wl_registry_bind(registry, name,
186 +                        &agl_shell_desktop_interface, 1);
187 +       } else if (strcmp(interface, "wl_output") == 0) {
188 +               r->output = wl_registry_bind(registry, name,
189 +                        &wl_output_interface, 1);
190         }
191  }
192  
193 @@ -157,6 +185,57 @@ static const struct ivi_surface_listener ivi_surface_listener = {
194         handle_ivi_surface_configure,
195  };
196  
197 +static void handle_xdg_toplevel_configure(void *data,
198 +                               struct xdg_toplevel *xdg_toplevel,
199 +                               int32_t width, int32_t height, struct wl_array *states)
200 +{
201 +       (void)xdg_toplevel;
202 +       struct rvgpu_scanout *s = data;
203 +
204 +       s->window.w = (unsigned int)width;
205 +       s->window.h = (unsigned int)height;
206 +
207 +       wl_egl_window_resize(s->native->egl_window, width, height, 0, 0);
208 +}
209 +
210 +static const struct xdg_toplevel_listener xdg_toplevel_listener = {
211 +       handle_xdg_toplevel_configure,
212 +};
213 +
214 +static struct config_param {
215 +    struct rvgpu_egl_state *egl_state;
216 +    struct rvgpu_scanout *scanout;
217 +};
218 +
219 +static void handle_xdg_surface_configure(void *data,
220 +               struct xdg_surface *surface, uint32_t serial)
221 +{
222 +    struct config_param *cp = data;
223 +         struct rvgpu_scanout *s = cp->scanout;
224 +         struct rvgpu_egl_state *egl = cp->egl_state;
225 +
226 +    if (surface == NULL)
227 +        return;
228 +
229 +       xdg_surface_ack_configure(surface, serial);
230 +       if (s->native->wait_for_configure) {
231 +               if (egl->user_specified_scanouts){
232 +                       for (unsigned int i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) {
233 +                               if (egl->scanouts[i].params.enabled) {
234 +                                       rvgpu_egl_draw(egl, &egl->scanouts[i], false);
235 +                               }
236 +                       }
237 +               } else {
238 +                       rvgpu_egl_draw(egl, &egl->scanouts[0], false);
239 +               }
240 +               s->native->wait_for_configure = false;
241 +       }
242 +}
243 +
244 +static const struct xdg_surface_listener xdg_surface_listener = {
245 +       handle_xdg_surface_configure,
246 +};
247 +
248  static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
249                                  uint32_t serial, struct wl_surface *surface,
250                                  wl_fixed_t sx, wl_fixed_t sy)
251 @@ -493,6 +572,12 @@ static void rvgpu_wl_destroy_scanout(struct rvgpu_egl_state *e,
252         if (s->native->ivi_surface)
253                 ivi_surface_destroy(s->native->ivi_surface);
254  
255 +  if (s->native->xdg_toplevel)
256 +               xdg_toplevel_destroy(s->native->xdg_toplevel);
257 +
258 +       if (s->native->xdg_surface)
259 +               xdg_surface_destroy(s->native->xdg_surface);
260 +
261         wl_surface_destroy(s->native->surface);
262         free(s->native);
263  }
264 @@ -510,6 +595,12 @@ static void rvgpu_wl_free(struct rvgpu_egl_state *e)
265         if (r->shell)
266                 wl_shell_destroy(r->shell);
267  
268 +  if (r->wm_base)
269 +               xdg_wm_base_destroy(r->wm_base);
270 +
271 +       if (r->agl_shell_desktop)
272 +               agl_shell_desktop_destroy(r->agl_shell_desktop);
273 +
274         wl_seat_destroy(r->seat);
275         if (r->pointer)
276                 wl_pointer_destroy(r->pointer);
277 @@ -564,6 +655,21 @@ static void rvgpu_wl_process_events(struct rvgpu_egl_state *e, const void *ev,
278         }
279  }
280  
281 +static void create_opaque_region(struct rvgpu_egl_state *e,
282 +                                struct rvgpu_scanout *s)
283 +{
284 +       struct rvgpu_wl_state *r = to_wl(e);
285 +       struct wl_region *region =
286 +               wl_compositor_create_region(r->comp);
287 +       assert(region);
288 +       wl_region_add(region, 0, 0, (int)s->window.w,
289 +                               (int)s->window.h);
290 +       wl_surface_set_opaque_region(s->native->surface,
291 +                                               region);
292 +       wl_region_destroy(region);
293 +}
294 +
295 +
296  static void rvgpu_wl_set_scanout(struct rvgpu_egl_state *e,
297                                  struct rvgpu_scanout *s)
298  {
299 @@ -572,15 +678,9 @@ static void rvgpu_wl_set_scanout(struct rvgpu_egl_state *e,
300         if (!r->fullscreen) {
301                 s->window = s->virgl.box;
302                 if (s->native) {
303 -                       if (!r->translucent) {
304 -                               struct wl_region *region =
305 -                                       wl_compositor_create_region(r->comp);
306 -                               wl_region_add(region, 0, 0, (int)s->window.w,
307 -                                             (int)s->window.h);
308 -                               wl_surface_set_opaque_region(s->native->surface,
309 -                                                            region);
310 -                               wl_region_destroy(region);
311 -                       }
312 +      if (!r->translucent)
313 +                               create_opaque_region(e, s);
314 +
315                         wl_egl_window_resize(s->native->egl_window,
316                                              (int)s->window.w, (int)s->window.h,
317                                              0, 0);
318 @@ -629,6 +729,59 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
319                 assert(n->ivi_surface);
320                 ivi_surface_add_listener(n->ivi_surface, &ivi_surface_listener,
321                                          s);
322 +
323 +  } else if (r->wm_base) {
324 +    if (r->agl_shell_desktop){
325 +                       /* Default create window at the center of the AGL homescreen */
326 +                       unsigned int agl_x = 0;
327 +                       unsigned int agl_y = 215;
328 +                       unsigned int agl_w = 1080;
329 +                       unsigned int agl_h = 1500;
330 +                       if (sp && sp->agl_win_set) {
331 +                               agl_x = sp->agl_win.x;
332 +                               agl_y = sp->agl_win.y;
333 +                       }
334 +
335 +       /*
336 +                       * Because we can not resize the surface automatically, window size
337 +                       * have to be fit to the size of renderer box.
338 +                       */
339 +                       if (sp && sp->boxed) {
340 +                               agl_w = s->window.w;
341 +                               agl_h = s->window.h;
342 +                       }
343 +
344 +      agl_shell_desktop_set_app_property(r->agl_shell_desktop,
345 +                                       "rvgpu-renderer",
346 +                                       AGL_SHELL_DESKTOP_APP_ROLE_POPUP,
347 +                                       agl_x, agl_y,
348 +                                       0, 0, agl_w, agl_h,
349 +                                       r->output);
350 +               }
351 +      
352 +               n->xdg_surface =
353 +                       xdg_wm_base_get_xdg_surface(r->wm_base, n->surface);
354 +               assert(n->xdg_surface);
355 +
356 +    struct config_param *cp = malloc(sizeof(*cp));
357 +               assert(cp);
358 +
359 +               cp->egl_state = e;
360 +               cp->scanout = s;
361 +
362 +               xdg_surface_add_listener(n->xdg_surface,
363 +                                        &xdg_surface_listener, cp);
364 +               n->xdg_toplevel = xdg_surface_get_toplevel(n->xdg_surface);
365 +               assert(n->xdg_toplevel);
366 +
367 +               xdg_toplevel_add_listener(n->xdg_toplevel,
368 +                                         &xdg_toplevel_listener, s);
369 +
370 +               xdg_toplevel_set_app_id(n->xdg_toplevel, "rvgpu-renderer");
371 +               wl_surface_commit(n->surface);
372 +               n->wait_for_configure = true;
373 +               create_opaque_region(e, s);
374 +
375         } else if (r->shell) {
376                 char title[32];
377  
378 @@ -654,16 +807,9 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
379                                 NULL);
380                 } else {
381                         wl_shell_surface_set_toplevel(n->shell_surface);
382 -                       if (!r->translucent) {
383 -                               struct wl_region *region =
384 -                                       wl_compositor_create_region(r->comp);
385 -                               assert(region);
386 -                               wl_region_add(region, 0, 0, (int)s->window.w,
387 -                                             (int)s->window.h);
388 -                               wl_surface_set_opaque_region(n->surface,
389 -                                                            region);
390 -                               wl_region_destroy(region);
391 -                       }
392 +      if (!r->translucent)
393 +                               create_opaque_region(e, s);
394 +
395                 }
396         }
397  
398 @@ -677,6 +823,10 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
399         eglMakeCurrent(e->dpy, s->surface, s->surface, e->context);
400  
401         glGenFramebuffers(1, &s->fb);
402 +
403 +  if(!r->wm_base){
404 +               rvgpu_egl_draw(e, s, false);
405 +       }
406  }
407  
408  static const struct rvgpu_egl_callbacks wl_callbacks = {
409 diff --git a/src/rvgpu-renderer/renderer/rvgpu-egl.c b/src/rvgpu-renderer/renderer/rvgpu-egl.c
410 index a9dd398..6918843 100644
411 --- a/src/rvgpu-renderer/renderer/rvgpu-egl.c
412 +++ b/src/rvgpu-renderer/renderer/rvgpu-egl.c
413 @@ -21,6 +21,7 @@
414  #include <assert.h>
415  #include <err.h>
416  #include <stdlib.h>
417 +#include <stdio.h>
418  
419  #include <rvgpu-renderer/renderer/rvgpu-egl.h>
420  
421 @@ -146,6 +147,7 @@ void rvgpu_egl_free(struct rvgpu_egl_state *e)
422                 e->cb->free(e);
423  }
424  
425 +
426  void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
427                     bool vsync)
428  {
429 @@ -191,6 +193,7 @@ void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
430                                   (int)s->window.w, (int)s->window.h,
431                                   GL_COLOR_BUFFER_BIT, GL_NEAREST);
432         }
433 +
434         if (e->cb->draw)
435                 e->cb->draw(e, s, vsync);
436         else
437 diff --git a/src/rvgpu-renderer/rvgpu-renderer.c b/src/rvgpu-renderer/rvgpu-renderer.c
438 index 3e74289..40b78d4 100644
439 --- a/src/rvgpu-renderer/rvgpu-renderer.c
440 +++ b/src/rvgpu-renderer/rvgpu-renderer.c
441 @@ -52,6 +52,7 @@ static void usage(void)
442         info("\t-f\t\tRun in fullscreen mode\n");
443         info("\t-p port\t\tport for listening (default: %u)\n",
444              RVGPU_DEFAULT_PORT);
445 +  info("\t-w\t\tSet AGL window position\n");
446         info("\t-h\t\tShow this message\n");
447  
448         info("\nNote:\n");
449 @@ -189,7 +190,7 @@ int main(int argc, char **argv)
450  
451         memset(sp, 0, sizeof(sp));
452  
453 -       while ((opt = getopt(argc, argv, "afhi:c:s:S:b:B:p:g:")) != -1) {
454 +       while ((opt = getopt(argc, argv, "afhi:c:s:S:b:w:B:p:g:")) != -1) {
455                 switch (opt) {
456                 case 'a':
457                         translucent = true;
458 @@ -240,6 +241,13 @@ int main(int argc, char **argv)
459                         }
460                         cp->boxed = true;
461                         break;
462 +    case 'w':
463 +      if (sscanf(optarg, "%u,%u",
464 +        &cp->agl_win.x, &cp->agl_win.y) != 2) {
465 +        errx(1, "invalid AGL popup application window%s", optarg);
466 +      }
467 +      cp->agl_win_set = true;
468 +      break;
469                 case 'i':
470                         cp->id = (uint32_t)sanity_strtonum(
471                                 optarg, 1, UINT32_MAX, &errstr);
472 @@ -300,7 +308,6 @@ int main(int argc, char **argv)
473                 s->params = sp[i];
474                 if (sp[i].enabled) {
475                         rvgpu_egl_create_scanout(egl, &egl->scanouts[i]);
476 -                       rvgpu_egl_draw(egl, &egl->scanouts[i], false);
477                 }
478         }
479  
480 -- 
481 2.25.1
482