From 72cbcead969de5b34709ac706a3881636010b6f7 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 18 Apr 2023 11:32:37 +0400 Subject: egl: no need to lookup EGL functions manually MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libepoxy handles loading the function pointer and dispatching the call, so you don't have to worry about it. Signed-off-by: Marc-André Lureau Message-Id: <20230515132455.1025608-1-marcandre.lureau@redhat.com> --- ui/egl-helpers.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'ui/egl-helpers.c') diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 4203163ace..60385c1f48 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -439,10 +439,8 @@ static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native, /* In practise any EGL 1.5 implementation would support the EXT extension */ if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) { - PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT = - (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); - if (getPlatformDisplayEXT && platform != 0) { - dpy = getPlatformDisplayEXT(platform, native, NULL); + if (platform != 0) { + dpy = eglGetPlatformDisplayEXT(platform, native, NULL); } } -- cgit 1.4.1 From 044ca4bf45b5bc232a2d699a9e63f359b1b85df6 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:38 +0400 Subject: ui/egl: export qemu_egl_get_error_string() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will be used from other units. Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-2-marcandre.lureau@redhat.com> --- include/ui/egl-helpers.h | 2 ++ ui/egl-helpers.c | 12 +++++------- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'ui/egl-helpers.c') diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 53d953ddf4..2cf6633ad2 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -67,4 +67,6 @@ bool qemu_egl_has_dmabuf(void); bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp); +const char *qemu_egl_get_error_string(void); + #endif /* EGL_HELPERS_H */ diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 60385c1f48..26d43e0213 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -28,8 +28,7 @@ DisplayGLMode qemu_egl_mode; /* ------------------------------------------------------------------ */ -#if defined(CONFIG_X11) || defined(CONFIG_GBM) -static const char *egl_get_error_string(void) +const char *qemu_egl_get_error_string(void) { EGLint error = eglGetError(); @@ -68,7 +67,6 @@ static const char *egl_get_error_string(void) return "Unknown EGL error"; } } -#endif static void egl_fb_delete_texture(egl_fb *fb) { @@ -480,20 +478,20 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, qemu_egl_display = qemu_egl_get_display(dpy, platform); if (qemu_egl_display == EGL_NO_DISPLAY) { - error_report("egl: eglGetDisplay failed: %s", egl_get_error_string()); + error_report("egl: eglGetDisplay failed: %s", qemu_egl_get_error_string()); return -1; } b = eglInitialize(qemu_egl_display, &major, &minor); if (b == EGL_FALSE) { - error_report("egl: eglInitialize failed: %s", egl_get_error_string()); + error_report("egl: eglInitialize failed: %s", qemu_egl_get_error_string()); return -1; } b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API); if (b == EGL_FALSE) { error_report("egl: eglBindAPI failed (%s mode): %s", - gles ? "gles" : "core", egl_get_error_string()); + gles ? "gles" : "core", qemu_egl_get_error_string()); return -1; } @@ -502,7 +500,7 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, &qemu_egl_config, 1, &n); if (b == EGL_FALSE || n != 1) { error_report("egl: eglChooseConfig failed (%s mode): %s", - gles ? "gles" : "core", egl_get_error_string()); + gles ? "gles" : "core", qemu_egl_get_error_string()); return -1; } -- cgit 1.4.1 From 39324b49669c72b00cf3adc93d9dc7cf702bf11f Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:49 +0400 Subject: ui: add egl-headless support on win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make GBM optional for EGL code, and enable the build for win32. Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-13-marcandre.lureau@redhat.com> --- include/ui/egl-helpers.h | 7 ++++++- qapi/ui.json | 5 ++--- ui/egl-headless.c | 20 +++++++++++++------- ui/egl-helpers.c | 38 +++++++++++++++++++++++++++++++------- ui/meson.build | 6 +++--- 5 files changed, 55 insertions(+), 21 deletions(-) (limited to 'ui/egl-helpers.c') diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 2cf6633ad2..6c4eb5dd70 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -36,11 +36,12 @@ void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip); void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, int x, int y, double scale_x, double scale_y); +extern EGLContext qemu_egl_rn_ctx; + #ifdef CONFIG_GBM 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, DisplayGLMode mode); int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, @@ -62,6 +63,10 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode); #endif +#ifdef WIN32 +int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode); +#endif + EGLContext qemu_egl_init_ctx(void); bool qemu_egl_has_dmabuf(void); diff --git a/qapi/ui.json b/qapi/ui.json index 2755395483..bb06fb6039 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1484,8 +1484,7 @@ { 'name': 'none' }, { 'name': 'gtk', 'if': 'CONFIG_GTK' }, { 'name': 'sdl', 'if': 'CONFIG_SDL' }, - { 'name': 'egl-headless', - 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, + { 'name': 'egl-headless', 'if': 'CONFIG_OPENGL' }, { 'name': 'curses', 'if': 'CONFIG_CURSES' }, { 'name': 'cocoa', 'if': 'CONFIG_COCOA' }, { 'name': 'spice-app', 'if': 'CONFIG_SPICE' }, @@ -1525,7 +1524,7 @@ 'cocoa': { 'type': 'DisplayCocoa', 'if': 'CONFIG_COCOA' }, 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' }, 'egl-headless': { 'type': 'DisplayEGLHeadless', - 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, + 'if': 'CONFIG_OPENGL' }, 'dbus': { 'type': 'DisplayDBus', 'if': 'CONFIG_DBUS_DISPLAY' }, 'sdl': { 'type': 'DisplaySDL', 'if': 'CONFIG_SDL' } } diff --git a/ui/egl-headless.c b/ui/egl-headless.c index ef70e6a18e..e4177206f2 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -79,6 +79,8 @@ static void egl_scanout_texture(DisplayChangeListener *dcl, } } +#ifdef CONFIG_GBM + static void egl_scanout_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf) { @@ -110,6 +112,14 @@ static void egl_cursor_dmabuf(DisplayChangeListener *dcl, } } +static void egl_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + egl_dmabuf_release_texture(dmabuf); +} + +#endif + static void egl_cursor_position(DisplayChangeListener *dcl, uint32_t pos_x, uint32_t pos_y) { @@ -119,12 +129,6 @@ static void egl_cursor_position(DisplayChangeListener *dcl, edpy->pos_y = pos_y; } -static void egl_release_dmabuf(DisplayChangeListener *dcl, - QemuDmaBuf *dmabuf) -{ - egl_dmabuf_release_texture(dmabuf); -} - static void egl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h) @@ -160,10 +164,12 @@ static const DisplayChangeListenerOps egl_ops = { .dpy_gl_scanout_disable = egl_scanout_disable, .dpy_gl_scanout_texture = egl_scanout_texture, +#ifdef CONFIG_GBM .dpy_gl_scanout_dmabuf = egl_scanout_dmabuf, .dpy_gl_cursor_dmabuf = egl_cursor_dmabuf, - .dpy_gl_cursor_position = egl_cursor_position, .dpy_gl_release_dmabuf = egl_release_dmabuf, +#endif + .dpy_gl_cursor_position = egl_cursor_position, .dpy_gl_update = egl_scanout_flush, }; diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 26d43e0213..d1ef3c07dd 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -199,11 +199,12 @@ void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, /* ---------------------------------------------------------------------- */ +EGLContext qemu_egl_rn_ctx; + #ifdef CONFIG_GBM int qemu_egl_rn_fd; struct gbm_device *qemu_egl_rn_gbm_dev; -EGLContext qemu_egl_rn_ctx; int egl_rendernode_init(const char *rendernode, DisplayGLMode mode) { @@ -400,7 +401,7 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win) /* ---------------------------------------------------------------------- */ -#if defined(CONFIG_X11) || defined(CONFIG_GBM) +#if defined(CONFIG_X11) || defined(CONFIG_GBM) || defined(WIN32) /* * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed @@ -508,6 +509,9 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, return 0; } +#endif + +#if defined(CONFIG_X11) || defined(CONFIG_GBM) int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode) { #ifdef EGL_KHR_platform_x11 @@ -525,7 +529,14 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode) return qemu_egl_init_dpy(dpy, 0, mode); #endif } +#endif + +#ifdef WIN32 +int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode) +{ + return qemu_egl_init_dpy(dpy, 0, mode); +} #endif bool qemu_egl_has_dmabuf(void) @@ -577,15 +588,28 @@ bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp) return false; } -#ifdef CONFIG_GBM +#ifdef WIN32 + if (qemu_egl_init_dpy_win32(EGL_DEFAULT_DISPLAY, mode) < 0) { + error_setg(errp, "egl: init failed"); + return false; + } + qemu_egl_rn_ctx = qemu_egl_init_ctx(); + if (!qemu_egl_rn_ctx) { + error_setg(errp, "egl: egl_init_ctx failed"); + return false; + } +#elif defined(CONFIG_GBM) if (egl_rendernode_init(rendernode, mode) < 0) { error_setg(errp, "egl: render node init failed"); return false; } +#endif + + if (!qemu_egl_rn_ctx) { + error_setg(errp, "egl: not available on this platform"); + return false; + } + display_opengl = 1; return true; -#else - error_setg(errp, "egl: not available on this platform"); - return false; -#endif } diff --git a/ui/meson.build b/ui/meson.build index d84650676d..d81609fb0e 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -65,10 +65,10 @@ if opengl.found() ui_modules += {'opengl' : opengl_ss} endif -if opengl.found() and gbm.found() +if opengl.found() egl_headless_ss = ss.source_set() - egl_headless_ss.add(when: [opengl, gbm, pixman], - if_true: files('egl-headless.c')) + egl_headless_ss.add(when: [opengl, pixman], + if_true: [files('egl-headless.c'), gbm]) ui_modules += {'egl-headless' : egl_headless_ss} endif -- cgit 1.4.1 From afe8e0b6db2debeaf35f5bd43efa1ada90ba0847 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:50 +0400 Subject: ui/egl: default to GLES on windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows GL drivers are notoriously not very good. Otoh, ANGLE provides rock solid GLES implementation on top of direct3d. We should recommend it and default to ES when using EGL (users can easily override this if necessary) Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-14-marcandre.lureau@redhat.com> --- ui/egl-helpers.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ui/egl-helpers.c') diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index d1ef3c07dd..c2a3ace743 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -535,6 +535,10 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode) #ifdef WIN32 int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode) { + /* prefer GL ES, as that's what ANGLE supports */ + if (mode == DISPLAYGL_MODE_ON) { + mode = DISPLAYGL_MODE_ES; + } return qemu_egl_init_dpy(dpy, 0, mode); } #endif -- cgit 1.4.1 From da9eb580b7e28d70d344bb03e0fe5703c8d1892c Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:51 +0400 Subject: ui: add egl_fb_read_rect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to egl_fb_read(), same limitations, but with extra arguments to read a subset of the framebuffer. Used in following commits. Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-15-marcandre.lureau@redhat.com> --- include/ui/egl-helpers.h | 1 + ui/egl-helpers.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'ui/egl-helpers.c') diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 6c4eb5dd70..6e2f0c49a6 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -31,6 +31,7 @@ void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, void egl_fb_setup_new_tex(egl_fb *fb, int width, int height); void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip); void egl_fb_read(DisplaySurface *dst, egl_fb *src); +void egl_fb_read_rect(DisplaySurface *dst, egl_fb *src, int x, int y, int w, int h); void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip); void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index c2a3ace743..f38800e920 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -169,6 +169,20 @@ void egl_fb_read(DisplaySurface *dst, egl_fb *src) GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst)); } +void egl_fb_read_rect(DisplaySurface *dst, egl_fb *src, int x, int y, int w, int h) +{ + assert(surface_width(dst) == src->width); + assert(surface_height(dst) == src->height); + assert(surface_format(dst) == PIXMAN_x8r8g8b8); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glPixelStorei(GL_PACK_ROW_LENGTH, surface_stride(dst) / 4); + glReadPixels(x, y, w, h, + GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst) + x * 4); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); +} + void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip) { glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); -- cgit 1.4.1 From 06c63a34e633601caea8fe88abfeff0911809da3 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 6 Jun 2023 15:56:55 +0400 Subject: ui/egl: query ANGLE d3d device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check if ANGLE is being used with D3D backend. Signed-off-by: Marc-André Lureau Message-Id: <20230606115658.677673-19-marcandre.lureau@redhat.com> --- include/ui/egl-helpers.h | 1 + ui/egl-helpers.c | 32 +++++++++++++++++++++++++++++++- ui/trace-events | 3 +++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'ui/egl-helpers.c') diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 6e2f0c49a6..4b8c0d2281 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -12,6 +12,7 @@ extern EGLDisplay *qemu_egl_display; extern EGLConfig qemu_egl_config; extern DisplayGLMode qemu_egl_mode; +extern bool qemu_egl_angle_d3d; typedef struct egl_fb { int width; diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index f38800e920..8f9fbf583e 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -15,16 +15,19 @@ * License along with this library; if not, see . */ #include "qemu/osdep.h" + #include "qemu/drm.h" #include "qemu/error-report.h" #include "ui/console.h" #include "ui/egl-helpers.h" #include "sysemu/sysemu.h" #include "qapi/error.h" +#include "trace.h" EGLDisplay *qemu_egl_display; EGLConfig qemu_egl_config; DisplayGLMode qemu_egl_mode; +bool qemu_egl_angle_d3d; /* ------------------------------------------------------------------ */ @@ -553,7 +556,34 @@ int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode) if (mode == DISPLAYGL_MODE_ON) { mode = DISPLAYGL_MODE_ES; } - return qemu_egl_init_dpy(dpy, 0, mode); + + if (qemu_egl_init_dpy(dpy, 0, mode) < 0) { + return -1; + } + +#ifdef EGL_D3D11_DEVICE_ANGLE + if (epoxy_has_egl_extension(qemu_egl_display, "EGL_EXT_device_query")) { + EGLDeviceEXT device; + void *d3d11_device; + + if (!eglQueryDisplayAttribEXT(qemu_egl_display, + EGL_DEVICE_EXT, + (EGLAttrib *)&device)) { + return 0; + } + + if (!eglQueryDeviceAttribEXT(device, + EGL_D3D11_DEVICE_ANGLE, + (EGLAttrib *)&d3d11_device)) { + return 0; + } + + trace_egl_init_d3d11_device(device); + qemu_egl_angle_d3d = device != NULL; + } +#endif + + return 0; } #endif diff --git a/ui/trace-events b/ui/trace-events index fe58675163..76b19a2995 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -162,3 +162,6 @@ dbus_clipboard_register(const char *bus_name) "peer %s" dbus_clipboard_unregister(const char *bus_name) "peer %s" dbus_scanout_texture(uint32_t tex_id, bool backing_y_0_top, uint32_t backing_width, uint32_t backing_height, uint32_t x, uint32_t y, uint32_t w, uint32_t h) "tex_id:%u y0top:%d back:%ux%u %u+%u-%ux%u" dbus_gl_gfx_switch(void *p) "surf: %p" + +# egl-helpers.c +egl_init_d3d11_device(void *p) "d3d device: %p" -- cgit 1.4.1