Hi, I can not compile git master anymore on my RHEL 7.3 installation ... I think it is due to this patch here. I now get:
CC ui/egl-headless.o /home/thuth/devel/qemu/ui/egl-headless.c: In function ‘egl_headless_init’: /home/thuth/devel/qemu/ui/egl-headless.c:142:5: error: implicit declaration of function ‘egl_rendernode_init’ [-Werror=implicit-function-declaration] if (egl_rendernode_init(NULL) < 0) { ^ /home/thuth/devel/qemu/ui/egl-headless.c:142:5: error: nested extern declaration of ‘egl_rendernode_init’ [-Werror=nested-externs] cc1: all warnings being treated as errors make: *** [ui/egl-headless.o] Error 1 The problem is likely that the prototype in egl-helpers.h is protected with some "#ifdef CONFIG_OPENGL_DMABUF" ... so should the code in egl-headless.c put into such conditionals, too? Thomas On 05.05.2017 12:41, Gerd Hoffmann wrote: > Add egl-headless user interface. It doesn't provide a real user > interface, it only provides opengl support using drm render nodes. > It will copy back the bits rendered by the guest using virgl back > to a DisplaySurface and kick the usual display update code paths, > so spice and vnc and screendump can pick it up. > > Use it this way: > qemu -display egl-headless -vnc $display > qemu -display egl-headless -spice gl=off,$args > > Note that you should prefer native spice opengl support (-spice > gl=on) if possible because that delivers better performance. > > Signed-off-by: Gerd Hoffmann <kra...@redhat.com> > --- > include/ui/console.h | 3 + > ui/egl-headless.c | 158 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > vl.c | 16 ++++++ > ui/Makefile.objs | 1 + > 4 files changed, 178 insertions(+) > create mode 100644 ui/egl-headless.c > > diff --git a/include/ui/console.h b/include/ui/console.h > index d759338816..7262bef6d3 100644 > --- a/include/ui/console.h > +++ b/include/ui/console.h > @@ -527,4 +527,7 @@ static inline void early_gtk_display_init(int opengl) > } > #endif > > +/* egl-headless.c */ > +void egl_headless_init(void); > + > #endif > diff --git a/ui/egl-headless.c b/ui/egl-headless.c > new file mode 100644 > index 0000000000..d8d800f8a6 > --- /dev/null > +++ b/ui/egl-headless.c > @@ -0,0 +1,158 @@ > +#include "qemu/osdep.h" > +#include "qemu-common.h" > +#include "sysemu/sysemu.h" > +#include "ui/console.h" > +#include "ui/egl-helpers.h" > +#include "ui/egl-context.h" > + > +typedef struct egl_dpy { > + DisplayChangeListener dcl; > + DisplaySurface *ds; > + int width, height; > + GLuint texture; > + GLuint framebuffer; > + GLuint blit_texture; > + GLuint blit_framebuffer; > + bool y_0_top; > +} egl_dpy; > + > +static void egl_refresh(DisplayChangeListener *dcl) > +{ > + graphic_hw_update(dcl->con); > +} > + > +static void egl_gfx_update(DisplayChangeListener *dcl, > + int x, int y, int w, int h) > +{ > +} > + > +static void egl_gfx_switch(DisplayChangeListener *dcl, > + struct DisplaySurface *new_surface) > +{ > + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); > + > + edpy->ds = new_surface; > +} > + > +static void egl_scanout_disable(DisplayChangeListener *dcl) > +{ > + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); > + > + edpy->texture = 0; > + /* XXX: delete framebuffers here ??? */ > +} > + > +static void egl_scanout_texture(DisplayChangeListener *dcl, > + uint32_t backing_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) > +{ > + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); > + > + edpy->texture = backing_id; > + edpy->y_0_top = backing_y_0_top; > + > + /* source framebuffer */ > + if (!edpy->framebuffer) { > + glGenFramebuffers(1, &edpy->framebuffer); > + } > + glBindFramebuffer(GL_FRAMEBUFFER_EXT, edpy->framebuffer); > + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, > + GL_TEXTURE_2D, edpy->texture, 0); > + > + /* dest framebuffer */ > + if (!edpy->blit_framebuffer) { > + glGenFramebuffers(1, &edpy->blit_framebuffer); > + glGenTextures(1, &edpy->blit_texture); > + edpy->width = 0; > + edpy->height = 0; > + } > + if (edpy->width != backing_width || edpy->height != backing_height) { > + edpy->width = backing_width; > + edpy->height = backing_height; > + glBindTexture(GL_TEXTURE_2D, edpy->blit_texture); > + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, > + edpy->width, edpy->height, > + 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); > + glBindFramebuffer(GL_FRAMEBUFFER_EXT, edpy->blit_framebuffer); > + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, > GL_COLOR_ATTACHMENT0_EXT, > + GL_TEXTURE_2D, edpy->blit_texture, 0); > + } > +} > + > +static void egl_scanout_flush(DisplayChangeListener *dcl, > + uint32_t x, uint32_t y, > + uint32_t w, uint32_t h) > +{ > + egl_dpy *edpy = container_of(dcl, egl_dpy, dcl); > + GLuint y1, y2; > + > + if (!edpy->texture || !edpy->ds) { > + return; > + } > + assert(surface_width(edpy->ds) == edpy->width); > + assert(surface_height(edpy->ds) == edpy->height); > + assert(surface_format(edpy->ds) == PIXMAN_x8r8g8b8); > + > + /* blit framebuffer, flip if needed */ > + glBindFramebuffer(GL_READ_FRAMEBUFFER, edpy->framebuffer); > + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, edpy->blit_framebuffer); > + glViewport(0, 0, edpy->width, edpy->height); > + y1 = edpy->y_0_top ? edpy->height : 0; > + y2 = edpy->y_0_top ? 0 : edpy->height; > + glBlitFramebuffer(0, y1, edpy->width, y2, > + 0, 0, edpy->width, edpy->height, > + GL_COLOR_BUFFER_BIT, GL_NEAREST); > + > + /* read pixels to surface */ > + glBindFramebuffer(GL_READ_FRAMEBUFFER, edpy->blit_framebuffer); > + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); > + glReadPixels(0, 0, edpy->width, edpy->height, > + GL_BGRA, GL_UNSIGNED_BYTE, surface_data(edpy->ds)); > + > + /* notify about updates */ > + dpy_gfx_update(edpy->dcl.con, x, y, w, h); > +} > + > +static const DisplayChangeListenerOps egl_ops = { > + .dpy_name = "egl-headless", > + .dpy_refresh = egl_refresh, > + .dpy_gfx_update = egl_gfx_update, > + .dpy_gfx_switch = egl_gfx_switch, > + > + .dpy_gl_ctx_create = qemu_egl_create_context, > + .dpy_gl_ctx_destroy = qemu_egl_destroy_context, > + .dpy_gl_ctx_make_current = qemu_egl_make_context_current, > + .dpy_gl_ctx_get_current = qemu_egl_get_current_context, > + > + .dpy_gl_scanout_disable = egl_scanout_disable, > + .dpy_gl_scanout_texture = egl_scanout_texture, > + .dpy_gl_update = egl_scanout_flush, > +}; > + > +void egl_headless_init(void) > +{ > + QemuConsole *con; > + egl_dpy *edpy; > + int idx; > + > + if (egl_rendernode_init(NULL) < 0) { > + error_report("egl: render node init failed"); > + exit(1); > + } > + > + for (idx = 0;; idx++) { > + con = qemu_console_lookup_by_index(idx); > + if (!con || !qemu_console_is_graphic(con)) { > + break; > + } > + > + edpy = g_new0(egl_dpy, 1); > + edpy->dcl.con = con; > + edpy->dcl.ops = &egl_ops; > + register_displaychangelistener(&edpy->dcl); > + } > +} > diff --git a/vl.c b/vl.c > index f46e070e0d..4e76e0ceb4 100644 > --- a/vl.c > +++ b/vl.c > @@ -2050,6 +2050,7 @@ typedef enum DisplayType { > DT_SDL, > DT_COCOA, > DT_GTK, > + DT_EGL, > DT_NONE, > } DisplayType; > > @@ -2127,6 +2128,15 @@ static DisplayType select_display(const char *p) > error_report("VNC requires a display argument vnc=<display>"); > exit(1); > } > + } else if (strstart(p, "egl-headless", &opts)) { > +#ifdef CONFIG_OPENGL > + request_opengl = 1; > + display_opengl = 1; > + display = DT_EGL; > +#else > + fprintf(stderr, "egl support is disabled\n"); > + exit(1); > +#endif > } else if (strstart(p, "curses", &opts)) { > #ifdef CONFIG_CURSES > display = DT_CURSES; > @@ -4662,6 +4672,12 @@ int main(int argc, char **argv, char **envp) > qemu_spice_display_init(); > } > > +#ifdef CONFIG_OPENGL > + if (display_type == DT_EGL) { > + egl_headless_init(); > + } > +#endif > + > if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { > exit(1); > } > diff --git a/ui/Makefile.objs b/ui/Makefile.objs > index 27566b32f1..aac6ae8bef 100644 > --- a/ui/Makefile.objs > +++ b/ui/Makefile.objs > @@ -33,6 +33,7 @@ common-obj-y += shader.o > common-obj-y += console-gl.o > common-obj-y += egl-helpers.o > common-obj-y += egl-context.o > +common-obj-y += egl-headless.o > ifeq ($(CONFIG_GTK_GL),y) > common-obj-$(CONFIG_GTK) += gtk-gl-area.o > else >