From 54d208ffdae20fd2bee745a037607a762d3a82a9 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 18 Jun 2018 13:21:41 +0200 Subject: [PATCH 1/3] Add gles support to egl-helpers, wire up in egl-headless and gtk. Add support for OpenGL ES to egl-helpers. Wire up the new option for egl-headless and gtk UIs. egl-headless actually works fine. gtk hits a not-yet implemented code path in libEGL when trying to use gles mode: libEGL warning: FIXME: egl/x11 doesn't support front buffer rendering. (This is mesa 17.2.3). Cc: Tomeu Vizoso Signed-off-by: Gerd Hoffmann Reviewed-by: Tomeu Vizoso Tested-by: Tomeu Vizoso Message-id: 20180618112141.23398-1-kraxel@redhat.com --- include/ui/egl-helpers.h | 7 ++--- include/ui/gtk.h | 2 +- ui/egl-context.c | 11 ++++++-- ui/egl-headless.c | 3 ++- ui/egl-helpers.c | 55 ++++++++++++++++++++++++++++------------ ui/gtk-egl.c | 4 +-- ui/gtk.c | 7 ++--- ui/spice-core.c | 3 ++- 8 files changed, 61 insertions(+), 31 deletions(-) diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 747233ce58..9db7293bdb 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -7,6 +7,7 @@ extern EGLDisplay *qemu_egl_display; extern EGLConfig qemu_egl_config; +extern DisplayGLMode qemu_egl_mode; typedef struct egl_fb { int width; @@ -34,7 +35,7 @@ extern int qemu_egl_rn_fd; extern struct gbm_device *qemu_egl_rn_gbm_dev; extern EGLContext qemu_egl_rn_ctx; -int egl_rendernode_init(const char *rendernode); +int egl_rendernode_init(const char *rendernode, DisplayGLMode mode); int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc); void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); @@ -44,8 +45,8 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win); -int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy); -int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy); +int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode); +int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode); EGLContext qemu_egl_init_ctx(void); #endif /* EGL_HELPERS_H */ diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 2922fc64b2..a79780afc7 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -127,7 +127,7 @@ void gd_egl_release_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); void gd_egl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); -void gtk_egl_init(void); +void gtk_egl_init(DisplayGLMode mode); int gd_egl_make_current(DisplayChangeListener *dcl, QEMUGLContext ctx); diff --git a/ui/egl-context.c b/ui/egl-context.c index 2161969abe..78e6c7ab7c 100644 --- a/ui/egl-context.c +++ b/ui/egl-context.c @@ -6,15 +6,22 @@ QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl, QEMUGLParams *params) { EGLContext ctx; - EGLint ctx_att[] = { + EGLint ctx_att_core[] = { EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, EGL_CONTEXT_CLIENT_VERSION, params->major_ver, EGL_CONTEXT_MINOR_VERSION_KHR, params->minor_ver, EGL_NONE }; + EGLint ctx_att_gles[] = { + EGL_CONTEXT_CLIENT_VERSION, params->major_ver, + EGL_CONTEXT_MINOR_VERSION_KHR, params->minor_ver, + EGL_NONE + }; + bool gles = (qemu_egl_mode == DISPLAYGL_MODE_ES); ctx = eglCreateContext(qemu_egl_display, qemu_egl_config, - eglGetCurrentContext(), ctx_att); + eglGetCurrentContext(), + gles ? ctx_att_gles : ctx_att_core); return ctx; } diff --git a/ui/egl-headless.c b/ui/egl-headless.c index 7c877122d3..42a41310b0 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -171,11 +171,12 @@ static void early_egl_headless_init(DisplayOptions *opts) static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) { + DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_ON; QemuConsole *con; egl_dpy *edpy; int idx; - if (egl_rendernode_init(NULL) < 0) { + if (egl_rendernode_init(NULL, mode) < 0) { error_report("egl: render node init failed"); exit(1); } diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 16dc3ded36..71b6a97bd1 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -24,6 +24,7 @@ EGLDisplay *qemu_egl_display; EGLConfig qemu_egl_config; +DisplayGLMode qemu_egl_mode; /* ------------------------------------------------------------------ */ @@ -191,7 +192,7 @@ static int qemu_egl_rendernode_open(const char *rendernode) return fd; } -int egl_rendernode_init(const char *rendernode) +int egl_rendernode_init(const char *rendernode, DisplayGLMode mode) { qemu_egl_rn_fd = -1; int rc; @@ -208,7 +209,8 @@ int egl_rendernode_init(const char *rendernode) goto err; } - rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev); + rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev, + mode); if (rc != 0) { /* qemu_egl_init_dpy_mesa reports error */ goto err; @@ -392,9 +394,10 @@ static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native, } static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, - EGLenum platform) + EGLenum platform, + DisplayGLMode mode) { - static const EGLint conf_att_gl[] = { + static const EGLint conf_att_core[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_RED_SIZE, 5, @@ -403,9 +406,19 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, EGL_ALPHA_SIZE, 0, EGL_NONE, }; + static const EGLint conf_att_gles[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 5, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_NONE, + }; EGLint major, minor; EGLBoolean b; EGLint n; + bool gles = (mode == DISPLAYGL_MODE_ES); qemu_egl_display = qemu_egl_get_display(dpy, platform); if (qemu_egl_display == EGL_NO_DISPLAY) { @@ -419,50 +432,60 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, return -1; } - b = eglBindAPI(EGL_OPENGL_API); + b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API); if (b == EGL_FALSE) { - error_report("egl: eglBindAPI failed"); + error_report("egl: eglBindAPI failed (%s mode)", + gles ? "gles" : "core"); return -1; } - b = eglChooseConfig(qemu_egl_display, conf_att_gl, + b = eglChooseConfig(qemu_egl_display, + gles ? conf_att_gles : conf_att_core, &qemu_egl_config, 1, &n); if (b == EGL_FALSE || n != 1) { - error_report("egl: eglChooseConfig failed"); + error_report("egl: eglChooseConfig failed (%s mode)", + gles ? "gles" : "core"); return -1; } + + qemu_egl_mode = gles ? DISPLAYGL_MODE_ES : DISPLAYGL_MODE_CORE; return 0; } -int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy) +int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode) { #ifdef EGL_KHR_platform_x11 - return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR); + return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR, mode); #else - return qemu_egl_init_dpy(dpy, 0); + return qemu_egl_init_dpy(dpy, 0, mode); #endif } -int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy) +int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode) { #ifdef EGL_MESA_platform_gbm - return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA); + return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA, mode); #else - return qemu_egl_init_dpy(dpy, 0); + return qemu_egl_init_dpy(dpy, 0, mode); #endif } EGLContext qemu_egl_init_ctx(void) { - static const EGLint ctx_att_gl[] = { + static const EGLint ctx_att_core[] = { EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, EGL_NONE }; + static const EGLint ctx_att_gles[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + bool gles = (qemu_egl_mode == DISPLAYGL_MODE_ES); EGLContext ectx; EGLBoolean b; ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT, - ctx_att_gl); + gles ? ctx_att_gles : ctx_att_core); if (ectx == EGL_NO_CONTEXT) { error_report("egl: eglCreateContext failed"); return NULL; diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 9390c6762e..fb00ad12ec 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -280,12 +280,12 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); } -void gtk_egl_init(void) +void gtk_egl_init(DisplayGLMode mode) { GdkDisplay *gdk_display = gdk_display_get_default(); Display *x11_display = gdk_x11_display_get_xdisplay(gdk_display); - if (qemu_egl_init_dpy_x11(x11_display) < 0) { + if (qemu_egl_init_dpy_x11(x11_display, mode) < 0) { return; } diff --git a/ui/gtk.c b/ui/gtk.c index 903f136b8f..5cce6ed42d 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2485,10 +2485,6 @@ static void early_gtk_display_init(DisplayOptions *opts) assert(opts->type == DISPLAY_TYPE_GTK); if (opts->has_gl && opts->gl != DISPLAYGL_MODE_OFF) { - if (opts->gl == DISPLAYGL_MODE_ES) { - error_report("gtk: opengl es not supported"); - return; - } #if defined(CONFIG_OPENGL) #if defined(CONFIG_GTK_GL) && defined(GDK_WINDOWING_WAYLAND) if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) { @@ -2497,7 +2493,8 @@ static void early_gtk_display_init(DisplayOptions *opts) } else #endif { - gtk_egl_init(); + DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_ON; + gtk_egl_init(mode); } #endif } diff --git a/ui/spice-core.c b/ui/spice-core.c index ae8921a201..f8c0878529 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -829,7 +829,8 @@ void qemu_spice_init(void) "incompatible with -spice port/tls-port"); exit(1); } - if (egl_rendernode_init(qemu_opt_get(opts, "rendernode")) != 0) { + if (egl_rendernode_init(qemu_opt_get(opts, "rendernode"), + DISPLAYGL_MODE_ON) != 0) { error_report("Failed to initialize EGL render node for SPICE GL"); exit(1); } From 48db08cf1619afde2ad0f7df11ba3ba54c49112b Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Tue, 26 Jun 2018 09:40:17 +0300 Subject: [PATCH 2/3] sdl2: fix copypaste issues This patch fixes text and mouse event processing. These functions used 'key' field of the event instead of appropriate 'text', 'motion', 'button', or 'wheel'. Signed-off-by: Pavel Dovgalyuk Signed-off-by: Maria Klimushenkova Message-id: 20180626064017.17031.47954.stgit@pasha-VirtualBox Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/sdl2.c b/ui/sdl2.c index 3ae4719c32..3fff9f5b63 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -424,7 +424,7 @@ static void handle_keyup(SDL_Event *ev) static void handle_textinput(SDL_Event *ev) { - struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->text.windowID); QemuConsole *con = scon ? scon->dcl.con : NULL; if (qemu_console_is_graphic(con)) { @@ -436,7 +436,7 @@ static void handle_textinput(SDL_Event *ev) static void handle_mousemotion(SDL_Event *ev) { int max_x, max_y; - struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->motion.windowID); if (!qemu_console_is_graphic(scon->dcl.con)) { return; @@ -468,7 +468,7 @@ static void handle_mousebutton(SDL_Event *ev) { int buttonstate = SDL_GetMouseState(NULL, NULL); SDL_MouseButtonEvent *bev; - struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->button.windowID); if (!qemu_console_is_graphic(scon->dcl.con)) { return; @@ -492,7 +492,7 @@ static void handle_mousebutton(SDL_Event *ev) static void handle_mousewheel(SDL_Event *ev) { - struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->wheel.windowID); SDL_MouseWheelEvent *wev = &ev->wheel; InputButton btn; From 49213b721f4620364aa09142b5f4d559fed26b53 Mon Sep 17 00:00:00 2001 From: Pavel Dovgalyuk Date: Tue, 26 Jun 2018 09:47:29 +0300 Subject: [PATCH 3/3] sdl2: add checking for NULL Sometimes SDL2 console can't be retrieved on events and scon variable becomes NULL. This patch prevents processing of the events when the console is not available. Signed-off-by: Pavel Dovgalyuk Signed-off-by: Maria Klimushenkova Message-id: 20180626064729.18070.47600.stgit@pasha-VirtualBox Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/sdl2.c b/ui/sdl2.c index 3fff9f5b63..76e59427cc 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -438,7 +438,7 @@ static void handle_mousemotion(SDL_Event *ev) int max_x, max_y; struct sdl2_console *scon = get_scon_from_window(ev->motion.windowID); - if (!qemu_console_is_graphic(scon->dcl.con)) { + if (!scon || !qemu_console_is_graphic(scon->dcl.con)) { return; } @@ -470,7 +470,7 @@ static void handle_mousebutton(SDL_Event *ev) SDL_MouseButtonEvent *bev; struct sdl2_console *scon = get_scon_from_window(ev->button.windowID); - if (!qemu_console_is_graphic(scon->dcl.con)) { + if (!scon || !qemu_console_is_graphic(scon->dcl.con)) { return; } @@ -496,7 +496,7 @@ static void handle_mousewheel(SDL_Event *ev) SDL_MouseWheelEvent *wev = &ev->wheel; InputButton btn; - if (!qemu_console_is_graphic(scon->dcl.con)) { + if (!scon || !qemu_console_is_graphic(scon->dcl.con)) { return; }