qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] QEMU master is broken (was: [PATCH 6/6] opengl: add egl-hea


From: Thomas Huth
Subject: [Qemu-devel] QEMU master is broken (was: [PATCH 6/6] opengl: add egl-headless display)
Date: Wed, 17 May 2017 09:56:11 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0

 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 <address@hidden>
> ---
>  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
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]