aboutsummaryrefslogtreecommitdiffstats
path: root/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu
diff options
context:
space:
mode:
authorFumiya Kohzu <kohzu.fumiya@jp.panasonic.com>2023-06-22 20:17:58 +0900
committerFumiya Kohzu <kohzu.fumiya@jp.panasonic.com>2023-09-25 10:31:00 +0900
commit951ac4aae235477716db29f1c707a5f0e7edf895 (patch)
tree5f5764b3caf0e3512ad0208e15c7c844b9811cd7 /meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu
parentb3bb5faf49e6a6c4f490f6f842b7e0f13d4a477d (diff)
Unified HMI: initial commit
This is the initial commit for RVGPU of Unified HMI. `Unified HMI` is a common platform that promotes UX innovation in integrated cockpits and enables flexible information display from various applications across multiple displays. `RVGPU` is a client-server based rendering engine that creates 3D commands on a client device, sends them to a server for GPU rendering, and displays the results. - create new layer, meta-uhmi - create sub-layer, meta-rvgpu - add 1 feature to enable basesystem, agl-rvgpu Bug-AGL: SPEC-4744 Change-Id: I9b6f3966e3d5a859787f81c41b584fa686fd1f87 Signed-off-by: Fumiya Kohzu <kohzu.fumiya@jp.panasonic.com>
Diffstat (limited to 'meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu')
-rw-r--r--meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu.inc6
-rw-r--r--meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0001-Remove-some-rvgpu-command-options.patch160
-rw-r--r--meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0002-Add-agl-shell-desktop-and-xdg-shell-support.patch482
-rw-r--r--meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu_git.bb27
4 files changed, 675 insertions, 0 deletions
diff --git a/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu.inc b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu.inc
new file mode 100644
index 00000000..4a8e5357
--- /dev/null
+++ b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu.inc
@@ -0,0 +1,6 @@
+PV = "0.0+git${SRCPV}"
+SRCREV = "4b1f508003a7bf36256d5cc81986ef733e4cc79b"
+BRANCH ?= "main"
+SRC_URI = " \
+ git://github.com/unified-hmi/remote-virtio-gpu.git;protocol=https;branch=${BRANCH} \
+"
diff --git a/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0001-Remove-some-rvgpu-command-options.patch b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0001-Remove-some-rvgpu-command-options.patch
new file mode 100644
index 00000000..4548c53f
--- /dev/null
+++ b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0001-Remove-some-rvgpu-command-options.patch
@@ -0,0 +1,160 @@
+From 0fc1cf03f76d21cec5b859ff46bee146cd4e52f7 Mon Sep 17 00:00:00 2001
+From: murakami <murakami.kenta002@jp.panasonic.jp>
+Date: Fri, 28 Jul 2023 12:09:35 +0900
+Subject: [PATCH 1/2] Remove some rvgpu command options
+
+Remove vsync and card_index option supports from remote-virtio-gpu,
+because the kernel needs to be patched to run those options in
+rvgpu-proxy and rvgpu-renderer.
+
+Upstream-Status: Inappropriate [embedded specific]
+---
+ include/rvgpu-proxy/gpu/rvgpu-gpu-device.h | 1 -
+ src/rvgpu-proxy/gpu/rvgpu-gpu-device.c | 3 ---
+ src/rvgpu-proxy/rvgpu-proxy.c | 27 ++--------------------
+ src/rvgpu-renderer/rvgpu-renderer.c | 10 +++-----
+ 4 files changed, 5 insertions(+), 36 deletions(-)
+
+diff --git a/include/rvgpu-proxy/gpu/rvgpu-gpu-device.h b/include/rvgpu-proxy/gpu/rvgpu-gpu-device.h
+index eb34b6a..76d747a 100644
+--- a/include/rvgpu-proxy/gpu/rvgpu-gpu-device.h
++++ b/include/rvgpu-proxy/gpu/rvgpu-gpu-device.h
+@@ -35,7 +35,6 @@ struct gpu_device;
+
+ struct gpu_device_params {
+ bool split_resources;
+- int card_index;
+ unsigned int num_scanouts;
+ unsigned int mem_limit;
+ unsigned long framerate;
+diff --git a/src/rvgpu-proxy/gpu/rvgpu-gpu-device.c b/src/rvgpu-proxy/gpu/rvgpu-gpu-device.c
+index 947e81a..71f62ca 100644
+--- a/src/rvgpu-proxy/gpu/rvgpu-gpu-device.c
++++ b/src/rvgpu-proxy/gpu/rvgpu-gpu-device.c
+@@ -528,7 +528,6 @@ struct gpu_device *gpu_device_init(int lo_fd, int efd, uint32_t cidx,
+ if (capset != -1)
+ gpu_capset_init(g, capset);
+
+- info.card_index = params->card_index;
+ info.config = (__u8 *)&g->config;
+ info.config_kick = g->config_fd;
+
+@@ -939,8 +938,6 @@ static void gpu_device_trigger_vsync(struct gpu_device *g,
+ return;
+
+ hdr->flags |= VIRTIO_GPU_FLAG_VSYNC;
+- /* use padding bytes to pass scanout_id to virtio-gpu driver */
+- hdr->padding = g->scan_id;
+ add_resp(g, hdr, req);
+
+ if ((!vsync_ts.tv_sec) && (!vsync_ts.tv_nsec)) {
+diff --git a/src/rvgpu-proxy/rvgpu-proxy.c b/src/rvgpu-proxy/rvgpu-proxy.c
+index 6ff4e19..d082b72 100644
+--- a/src/rvgpu-proxy/rvgpu-proxy.c
++++ b/src/rvgpu-proxy/rvgpu-proxy.c
+@@ -47,7 +47,6 @@ static void usage(void)
+ info("\t-s scanout\tspecify scanout in form WxH@X,Y (default: %ux%u@0,0)\n",
+ DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ info("\t-f rate\t\tspecify virtual framerate (default: disabled)\n");
+- info("\t-i index\tspecify index 'n' for device /dev/dri/card<n>\n");
+ info("\t-n\t\tserver:port for connecting (max 4 hosts, default: %s:%s)\n",
+ RVGPU_DEFAULT_HOSTNAME, RVGPU_DEFAULT_PORT);
+ info("\t-h\t\tshow this message\n");
+@@ -79,7 +78,6 @@ int main(int argc, char **argv)
+ struct gpu_device_params params = {
+ .framerate = 0u,
+ .mem_limit = VMEM_DEFAULT_MB,
+- .card_index = -1,
+ .num_scanouts = 0u,
+ .dpys = { { .r = { .x = 0,
+ .y = 0,
+@@ -97,38 +95,17 @@ int main(int argc, char **argv)
+ };
+
+ pthread_t input_thread;
+- char path[64];
+ FILE *oomFile;
+- int lo_fd, epoll_fd, res, opt, capset = -1;
++ int lo_fd, epoll_fd, opt, capset = -1;
+ char *ip, *port, *errstr = NULL;
+
+- while ((opt = getopt(argc, argv, "hi:n:M:c:R:f:s:")) != -1) {
++ while ((opt = getopt(argc, argv, "h:n:M:c:R:f:s:")) != -1) {
+ switch (opt) {
+ case 'c':
+ capset = open(optarg, O_RDONLY);
+ if (capset == -1)
+ err(1, "open %s", optarg);
+ break;
+- case 'i':
+- params.card_index =
+- (int)sanity_strtonum(optarg, CARD_INDEX_MIN,
+- CARD_INDEX_MAX - 1,
+- &errstr);
+- if (errstr != NULL) {
+- warnx("Card index should be in [%u..%u]\n",
+- CARD_INDEX_MIN, CARD_INDEX_MAX - 1);
+- errx(1, "Invalid card index %s:%s", optarg,
+- errstr);
+- }
+-
+- snprintf(path, sizeof(path), "/dev/dri/card%d",
+- params.card_index);
+- res = access(path, F_OK);
+- if (res == 0)
+- errx(1, "device %s exists", path);
+- else if (errno != ENOENT)
+- err(1, "error while checking device %s", path);
+- break;
+ case 'M':
+ params.mem_limit = (unsigned int)sanity_strtonum(
+ optarg, VMEM_MIN_MB, VMEM_MAX_MB, &errstr);
+diff --git a/src/rvgpu-renderer/rvgpu-renderer.c b/src/rvgpu-renderer/rvgpu-renderer.c
+index 7166fb9..3e74289 100644
+--- a/src/rvgpu-renderer/rvgpu-renderer.c
++++ b/src/rvgpu-renderer/rvgpu-renderer.c
+@@ -52,7 +52,6 @@ static void usage(void)
+ info("\t-f\t\tRun in fullscreen mode\n");
+ info("\t-p port\t\tport for listening (default: %u)\n",
+ RVGPU_DEFAULT_PORT);
+- info("\t-v\t\tRun in vsync mode (eglSwapInterval 1)\n");
+ info("\t-h\t\tShow this message\n");
+
+ info("\nNote:\n");
+@@ -185,12 +184,12 @@ int main(int argc, char **argv)
+ unsigned int res_id, scanout;
+ uint16_t port_nr = RVGPU_DEFAULT_PORT;
+ FILE *input_stream = stdout;
+- bool fullscreen = false, vsync = false, translucent = false,
++ bool fullscreen = false, translucent = false,
+ user_specified_scanouts = false;
+
+ memset(sp, 0, sizeof(sp));
+
+- while ((opt = getopt(argc, argv, "afhvi:c:s:S:b:B:p:g:")) != -1) {
++ while ((opt = getopt(argc, argv, "afhi:c:s:S:b:B:p:g:")) != -1) {
+ switch (opt) {
+ case 'a':
+ translucent = true;
+@@ -269,9 +268,6 @@ int main(int argc, char **argv)
+ errstr);
+ }
+ break;
+- case 'v':
+- vsync = true;
+- break;
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+@@ -309,7 +305,7 @@ int main(int argc, char **argv)
+ }
+
+ while ((res_id = rvgpu_pr_dispatch(pr))) {
+- rvgpu_egl_drawall(egl, res_id, vsync);
++ rvgpu_egl_drawall(egl, res_id, false);
+ }
+
+ if (pp.capset)
+--
+2.17.1
+
diff --git a/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0002-Add-agl-shell-desktop-and-xdg-shell-support.patch b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0002-Add-agl-shell-desktop-and-xdg-shell-support.patch
new file mode 100644
index 00000000..db5a6922
--- /dev/null
+++ b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu/0002-Add-agl-shell-desktop-and-xdg-shell-support.patch
@@ -0,0 +1,482 @@
+From b60e0a361d29723643fe81b47bff8f86d5200258 Mon Sep 17 00:00:00 2001
+From: Kenta <murakami.kenta002@jp.panasonic.com>
+Date: Wed, 6 Sep 2023 18:44:22 +0900
+Subject: [PATCH] Add agl-shell-desktop and xdg-shell supports
+
+---
+ CMakeLists.txt | 25 +++
+ include/rvgpu-renderer/renderer/rvgpu-egl.h | 9 +-
+ src/rvgpu-renderer/CMakeLists.txt | 3 +
+ src/rvgpu-renderer/backend/rvgpu-gbm.c | 2 +
+ src/rvgpu-renderer/backend/rvgpu-wayland.c | 192 +++++++++++++++++---
+ src/rvgpu-renderer/renderer/rvgpu-egl.c | 3 +
+ src/rvgpu-renderer/rvgpu-renderer.c | 11 +-
+ 7 files changed, 220 insertions(+), 25 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index f569ca2..85c875a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -20,6 +20,31 @@ cmake_minimum_required(VERSION 3.2)
+ project(rvgpu C)
+ set(CMAKE_C_STANDARD 11)
+
++find_program(WAYLAND_SCANNER_EXECUTABLE wayland-scanner)
++
++message("generating agl-shell-desktop client files from: agl-shell-desktop.xml")
++
++execute_process ( COMMAND mkdir ${CMAKE_BINARY_DIR}/protocol)
++
++execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code
++ ${CMAKE_SYSROOT}/usr/share/agl-compositor/protocols/agl-shell-desktop.xml
++ ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.c)
++
++execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header
++ ${CMAKE_SYSROOT}/usr/share/agl-compositor/protocols/agl-shell-desktop.xml
++ ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.h)
++
++message("generating agl-shell-desktop client files from: xdg-shell.xml")
++
++execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code
++ ${CMAKE_SYSROOT}/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml
++ ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.c)
++
++execute_process ( COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header
++ ${CMAKE_SYSROOT}/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml
++ ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.h)
++
++
+ if (CMAKE_SYSROOT AND NOT ENV{PKG_CONFIG_LIBDIR})
+ set(ENV{PKG_CONFIG_DIR} "")
+ set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
+diff --git a/include/rvgpu-renderer/renderer/rvgpu-egl.h b/include/rvgpu-renderer/renderer/rvgpu-egl.h
+index ebd2bd2..dcff36a 100644
+--- a/include/rvgpu-renderer/renderer/rvgpu-egl.h
++++ b/include/rvgpu-renderer/renderer/rvgpu-egl.h
+@@ -59,6 +59,9 @@ struct rvgpu_scanout_params {
+ uint32_t id; /**< ID for scanout window (i.e. IVI id)*/
+ bool enabled; /**< enable/disable scanout */
+ bool boxed; /**< box is set by user */
++ struct rvgpu_box agl_win; /** Window position & limit on AGL */
++ bool agl_win_set;
++
+ };
+
+ struct rvgpu_scanout {
+@@ -118,6 +121,8 @@ struct rvgpu_egl_state {
+ bool spawn_support;
+
+ bool use_scissors;
++
++ bool user_specified_scanouts;
+ };
+
+ /** Initialize main context */
+@@ -150,11 +155,11 @@ void rvgpu_egl_destroy_scanout(struct rvgpu_egl_state *e,
+
+ /** Draw Virgl output on the surface */
+ void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
+- bool vsync);
++ bool vsync);
+
+ /** Redraw all scanouts with given resource id */
+ void rvgpu_egl_drawall(struct rvgpu_egl_state *e, unsigned int res_id,
+- bool vsync);
++ bool vsync);
+
+ /* Async event handling */
+ /** Call before polling */
+diff --git a/src/rvgpu-renderer/CMakeLists.txt b/src/rvgpu-renderer/CMakeLists.txt
+index dc5f5b0..c8a8c34 100644
+--- a/src/rvgpu-renderer/CMakeLists.txt
++++ b/src/rvgpu-renderer/CMakeLists.txt
+@@ -17,6 +17,8 @@
+
+
+ add_executable(rvgpu-renderer
++ ${CMAKE_BINARY_DIR}/protocol/agl-shell-desktop-protocol.c
++ ${CMAKE_BINARY_DIR}/protocol/xdg-shell-protocol.c
+ backend/rvgpu-wayland.c
+ backend/rvgpu-gbm.c
+ renderer/rvgpu-egl.c
+@@ -28,6 +30,7 @@ add_executable(rvgpu-renderer
+ target_include_directories(rvgpu-renderer
+ PRIVATE
+ ${PROJECT_SOURCE_DIR}/include
++ ${CMAKE_BINARY_DIR}/protocol
+ ${extlibs_INCLUDE_DIRS}
+ )
+ target_compile_definitions(rvgpu-renderer PRIVATE _GNU_SOURCE)
+diff --git a/src/rvgpu-renderer/backend/rvgpu-gbm.c b/src/rvgpu-renderer/backend/rvgpu-gbm.c
+index 4194b0d..b2b3ed3 100644
+--- a/src/rvgpu-renderer/backend/rvgpu-gbm.c
++++ b/src/rvgpu-renderer/backend/rvgpu-gbm.c
+@@ -259,6 +259,8 @@ static void rvgpu_gbm_create_scanout(struct rvgpu_egl_state *e,
+
+ eglMakeCurrent(e->dpy, s->surface, s->surface, e->context);
+ glGenFramebuffers(1, &s->fb);
++
++ rvgpu_egl_draw(e, s, false);
+ }
+
+ static void rvgpu_gbm_page_flip_handler(int fd, unsigned int sequence,
+diff --git a/src/rvgpu-renderer/backend/rvgpu-wayland.c b/src/rvgpu-renderer/backend/rvgpu-wayland.c
+index 0aaeaa7..c00ff00 100644
+--- a/src/rvgpu-renderer/backend/rvgpu-wayland.c
++++ b/src/rvgpu-renderer/backend/rvgpu-wayland.c
+@@ -39,12 +39,18 @@
+ #include <rvgpu-renderer/renderer/rvgpu-egl.h>
+ #include <rvgpu-renderer/renderer/rvgpu-input.h>
+
++#include "agl-shell-desktop-protocol.h"
++#include "xdg-shell-protocol.h"
++
+ struct rvgpu_native {
+ /* Window structures */
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct wl_egl_window *egl_window;
+ struct ivi_surface *ivi_surface;
++ struct xdg_surface *xdg_surface;
++ struct xdg_toplevel *xdg_toplevel;
++ bool wait_for_configure;
+ };
+
+ struct rvgpu_wl_state {
+@@ -58,6 +64,9 @@ struct rvgpu_wl_state {
+ struct wl_keyboard *keyboard;
+ struct wl_shell *shell;
+ struct ivi_application *ivi_app;
++ struct xdg_wm_base *wm_base;
++ struct agl_shell_desktop *agl_shell_desktop;
++ struct wl_output *output;
+
+ /* EGL structures */
+ struct rvgpu_egl_state egl;
+@@ -78,6 +87,16 @@ static inline struct rvgpu_wl_state *to_wl(struct rvgpu_egl_state *e)
+ return rvgpu_container_of(e, struct rvgpu_wl_state, egl);
+ }
+
++static void xdg_wm_base_ping(void *data, struct xdg_wm_base *shell,
++ uint32_t serial)
++{
++ xdg_wm_base_pong(shell, serial);
++}
++
++static const struct xdg_wm_base_listener xdg_wm_base_listener = {
++ xdg_wm_base_ping,
++};
++
+ static struct wl_seat_listener seat_listener;
+
+ static void registry_add_object(void *data, struct wl_registry *registry,
+@@ -98,8 +117,17 @@ static void registry_add_object(void *data, struct wl_registry *registry,
+ wl_registry_bind(registry, name, &wl_seat_interface, 1);
+ wl_seat_add_listener(r->seat, &seat_listener, r);
+ } else if (!strcmp(interface, "ivi_application")) {
+- r->ivi_app = wl_registry_bind(registry, name,
+- &ivi_application_interface, 1);
++ r->ivi_app = wl_registry_bind(registry, name, &ivi_application_interface, 1);
++ } else if (strcmp(interface, "xdg_wm_base") == 0) {
++ r->wm_base = wl_registry_bind(registry, name,
++ &xdg_wm_base_interface, 1);
++ xdg_wm_base_add_listener(r->wm_base, &xdg_wm_base_listener, r);
++ } else if (strcmp(interface, "agl_shell_desktop") == 0) {
++ r->agl_shell_desktop = wl_registry_bind(registry, name,
++ &agl_shell_desktop_interface, 1);
++ } else if (strcmp(interface, "wl_output") == 0) {
++ r->output = wl_registry_bind(registry, name,
++ &wl_output_interface, 1);
+ }
+ }
+
+@@ -157,6 +185,57 @@ static const struct ivi_surface_listener ivi_surface_listener = {
+ handle_ivi_surface_configure,
+ };
+
++static void handle_xdg_toplevel_configure(void *data,
++ struct xdg_toplevel *xdg_toplevel,
++ int32_t width, int32_t height, struct wl_array *states)
++{
++ (void)xdg_toplevel;
++ struct rvgpu_scanout *s = data;
++
++ s->window.w = (unsigned int)width;
++ s->window.h = (unsigned int)height;
++
++ wl_egl_window_resize(s->native->egl_window, width, height, 0, 0);
++}
++
++static const struct xdg_toplevel_listener xdg_toplevel_listener = {
++ handle_xdg_toplevel_configure,
++};
++
++static struct config_param {
++ struct rvgpu_egl_state *egl_state;
++ struct rvgpu_scanout *scanout;
++};
++
++static void handle_xdg_surface_configure(void *data,
++ struct xdg_surface *surface, uint32_t serial)
++{
++ struct config_param *cp = data;
++ struct rvgpu_scanout *s = cp->scanout;
++ struct rvgpu_egl_state *egl = cp->egl_state;
++
++ if (surface == NULL)
++ return;
++
++ xdg_surface_ack_configure(surface, serial);
++ if (s->native->wait_for_configure) {
++ if (egl->user_specified_scanouts){
++ for (unsigned int i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) {
++ if (egl->scanouts[i].params.enabled) {
++ rvgpu_egl_draw(egl, &egl->scanouts[i], false);
++ }
++ }
++ } else {
++ rvgpu_egl_draw(egl, &egl->scanouts[0], false);
++ }
++ s->native->wait_for_configure = false;
++ }
++}
++
++static const struct xdg_surface_listener xdg_surface_listener = {
++ handle_xdg_surface_configure,
++};
++
+ static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy)
+@@ -493,6 +572,12 @@ static void rvgpu_wl_destroy_scanout(struct rvgpu_egl_state *e,
+ if (s->native->ivi_surface)
+ ivi_surface_destroy(s->native->ivi_surface);
+
++ if (s->native->xdg_toplevel)
++ xdg_toplevel_destroy(s->native->xdg_toplevel);
++
++ if (s->native->xdg_surface)
++ xdg_surface_destroy(s->native->xdg_surface);
++
+ wl_surface_destroy(s->native->surface);
+ free(s->native);
+ }
+@@ -510,6 +595,12 @@ static void rvgpu_wl_free(struct rvgpu_egl_state *e)
+ if (r->shell)
+ wl_shell_destroy(r->shell);
+
++ if (r->wm_base)
++ xdg_wm_base_destroy(r->wm_base);
++
++ if (r->agl_shell_desktop)
++ agl_shell_desktop_destroy(r->agl_shell_desktop);
++
+ wl_seat_destroy(r->seat);
+ if (r->pointer)
+ wl_pointer_destroy(r->pointer);
+@@ -564,6 +655,21 @@ static void rvgpu_wl_process_events(struct rvgpu_egl_state *e, const void *ev,
+ }
+ }
+
++static void create_opaque_region(struct rvgpu_egl_state *e,
++ struct rvgpu_scanout *s)
++{
++ struct rvgpu_wl_state *r = to_wl(e);
++ struct wl_region *region =
++ wl_compositor_create_region(r->comp);
++ assert(region);
++ wl_region_add(region, 0, 0, (int)s->window.w,
++ (int)s->window.h);
++ wl_surface_set_opaque_region(s->native->surface,
++ region);
++ wl_region_destroy(region);
++}
++
++
+ static void rvgpu_wl_set_scanout(struct rvgpu_egl_state *e,
+ struct rvgpu_scanout *s)
+ {
+@@ -572,15 +678,9 @@ static void rvgpu_wl_set_scanout(struct rvgpu_egl_state *e,
+ if (!r->fullscreen) {
+ s->window = s->virgl.box;
+ if (s->native) {
+- if (!r->translucent) {
+- struct wl_region *region =
+- wl_compositor_create_region(r->comp);
+- wl_region_add(region, 0, 0, (int)s->window.w,
+- (int)s->window.h);
+- wl_surface_set_opaque_region(s->native->surface,
+- region);
+- wl_region_destroy(region);
+- }
++ if (!r->translucent)
++ create_opaque_region(e, s);
++
+ wl_egl_window_resize(s->native->egl_window,
+ (int)s->window.w, (int)s->window.h,
+ 0, 0);
+@@ -629,6 +729,59 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
+ assert(n->ivi_surface);
+ ivi_surface_add_listener(n->ivi_surface, &ivi_surface_listener,
+ s);
++
++ } else if (r->wm_base) {
++ if (r->agl_shell_desktop){
++ /* Default create window at the center of the AGL homescreen */
++ unsigned int agl_x = 0;
++ unsigned int agl_y = 215;
++ unsigned int agl_w = 1080;
++ unsigned int agl_h = 1500;
++ if (sp && sp->agl_win_set) {
++ agl_x = sp->agl_win.x;
++ agl_y = sp->agl_win.y;
++ }
++
++ /*
++ * Because we can not resize the surface automatically, window size
++ * have to be fit to the size of renderer box.
++ */
++ if (sp && sp->boxed) {
++ agl_w = s->window.w;
++ agl_h = s->window.h;
++ }
++
++ agl_shell_desktop_set_app_property(r->agl_shell_desktop,
++ "rvgpu-renderer",
++ AGL_SHELL_DESKTOP_APP_ROLE_POPUP,
++ agl_x, agl_y,
++ 0, 0, agl_w, agl_h,
++ r->output);
++ }
++
++ n->xdg_surface =
++ xdg_wm_base_get_xdg_surface(r->wm_base, n->surface);
++ assert(n->xdg_surface);
++
++ struct config_param *cp = malloc(sizeof(*cp));
++ assert(cp);
++
++ cp->egl_state = e;
++ cp->scanout = s;
++
++ xdg_surface_add_listener(n->xdg_surface,
++ &xdg_surface_listener, cp);
++ n->xdg_toplevel = xdg_surface_get_toplevel(n->xdg_surface);
++ assert(n->xdg_toplevel);
++
++ xdg_toplevel_add_listener(n->xdg_toplevel,
++ &xdg_toplevel_listener, s);
++
++ xdg_toplevel_set_app_id(n->xdg_toplevel, "rvgpu-renderer");
++ wl_surface_commit(n->surface);
++ n->wait_for_configure = true;
++ create_opaque_region(e, s);
++
+ } else if (r->shell) {
+ char title[32];
+
+@@ -654,16 +807,9 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
+ NULL);
+ } else {
+ wl_shell_surface_set_toplevel(n->shell_surface);
+- if (!r->translucent) {
+- struct wl_region *region =
+- wl_compositor_create_region(r->comp);
+- assert(region);
+- wl_region_add(region, 0, 0, (int)s->window.w,
+- (int)s->window.h);
+- wl_surface_set_opaque_region(n->surface,
+- region);
+- wl_region_destroy(region);
+- }
++ if (!r->translucent)
++ create_opaque_region(e, s);
++
+ }
+ }
+
+@@ -677,6 +823,10 @@ static void rvgpu_wl_create_scanout(struct rvgpu_egl_state *e,
+ eglMakeCurrent(e->dpy, s->surface, s->surface, e->context);
+
+ glGenFramebuffers(1, &s->fb);
++
++ if(!r->wm_base){
++ rvgpu_egl_draw(e, s, false);
++ }
+ }
+
+ static const struct rvgpu_egl_callbacks wl_callbacks = {
+diff --git a/src/rvgpu-renderer/renderer/rvgpu-egl.c b/src/rvgpu-renderer/renderer/rvgpu-egl.c
+index a9dd398..6918843 100644
+--- a/src/rvgpu-renderer/renderer/rvgpu-egl.c
++++ b/src/rvgpu-renderer/renderer/rvgpu-egl.c
+@@ -21,6 +21,7 @@
+ #include <assert.h>
+ #include <err.h>
+ #include <stdlib.h>
++#include <stdio.h>
+
+ #include <rvgpu-renderer/renderer/rvgpu-egl.h>
+
+@@ -146,6 +147,7 @@ void rvgpu_egl_free(struct rvgpu_egl_state *e)
+ e->cb->free(e);
+ }
+
++
+ void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
+ bool vsync)
+ {
+@@ -191,6 +193,7 @@ void rvgpu_egl_draw(struct rvgpu_egl_state *e, struct rvgpu_scanout *s,
+ (int)s->window.w, (int)s->window.h,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
++
+ if (e->cb->draw)
+ e->cb->draw(e, s, vsync);
+ else
+diff --git a/src/rvgpu-renderer/rvgpu-renderer.c b/src/rvgpu-renderer/rvgpu-renderer.c
+index 3e74289..40b78d4 100644
+--- a/src/rvgpu-renderer/rvgpu-renderer.c
++++ b/src/rvgpu-renderer/rvgpu-renderer.c
+@@ -52,6 +52,7 @@ static void usage(void)
+ info("\t-f\t\tRun in fullscreen mode\n");
+ info("\t-p port\t\tport for listening (default: %u)\n",
+ RVGPU_DEFAULT_PORT);
++ info("\t-w\t\tSet AGL window position\n");
+ info("\t-h\t\tShow this message\n");
+
+ info("\nNote:\n");
+@@ -189,7 +190,7 @@ int main(int argc, char **argv)
+
+ memset(sp, 0, sizeof(sp));
+
+- while ((opt = getopt(argc, argv, "afhi:c:s:S:b:B:p:g:")) != -1) {
++ while ((opt = getopt(argc, argv, "afhi:c:s:S:b:w:B:p:g:")) != -1) {
+ switch (opt) {
+ case 'a':
+ translucent = true;
+@@ -240,6 +241,13 @@ int main(int argc, char **argv)
+ }
+ cp->boxed = true;
+ break;
++ case 'w':
++ if (sscanf(optarg, "%u,%u",
++ &cp->agl_win.x, &cp->agl_win.y) != 2) {
++ errx(1, "invalid AGL popup application window%s", optarg);
++ }
++ cp->agl_win_set = true;
++ break;
+ case 'i':
+ cp->id = (uint32_t)sanity_strtonum(
+ optarg, 1, UINT32_MAX, &errstr);
+@@ -300,7 +308,6 @@ int main(int argc, char **argv)
+ s->params = sp[i];
+ if (sp[i].enabled) {
+ rvgpu_egl_create_scanout(egl, &egl->scanouts[i]);
+- rvgpu_egl_draw(egl, &egl->scanouts[i], false);
+ }
+ }
+
+--
+2.25.1
+
diff --git a/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu_git.bb b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu_git.bb
new file mode 100644
index 00000000..899f81bb
--- /dev/null
+++ b/meta-uhmi/meta-rvgpu/recipes-graphics/remote-virtio-gpu/remote-virtio-gpu_git.bb
@@ -0,0 +1,27 @@
+SUMMARY = "Remote virtual display userland"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE.md;md5=573c152503e0d9b97c8e0cc09fbb1ad2"
+
+require remote-virtio-gpu.inc
+
+SRC_URI:append = " \
+ file://0001-Remove-some-rvgpu-command-options.patch \
+ file://0002-Add-agl-shell-desktop-and-xdg-shell-support.patch \
+"
+
+S = "${WORKDIR}/git"
+
+DEPENDS = "virglrenderer virtual/libgbm wayland wayland-native libepoxy libinput linux-libc-headers agl-compositor virtio-loopback-driver"
+RDEPENDS:${PN} = " wayland libgles2"
+
+inherit cmake pkgconfig
+
+PACKAGECONFIG_CONFARGS += " \
+ -DCMAKE_BUILD_TYPE=Release \
+"
+
+FILES:SOLIBSDEV = ""
+FILES:${PN} += " \
+ ${libdir}/librvgpu.so* \
+"