qemu/ui/egl-headless.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "qemu-common.h"
   3#include "sysemu/sysemu.h"
   4#include "ui/console.h"
   5#include "ui/egl-helpers.h"
   6#include "ui/egl-context.h"
   7
   8typedef struct egl_dpy {
   9    DisplayChangeListener dcl;
  10    DisplaySurface *ds;
  11    egl_fb guest_fb;
  12    egl_fb blit_fb;
  13    bool y_0_top;
  14} egl_dpy;
  15
  16/* ------------------------------------------------------------------ */
  17
  18static void egl_refresh(DisplayChangeListener *dcl)
  19{
  20    graphic_hw_update(dcl->con);
  21}
  22
  23static void egl_gfx_update(DisplayChangeListener *dcl,
  24                           int x, int y, int w, int h)
  25{
  26}
  27
  28static void egl_gfx_switch(DisplayChangeListener *dcl,
  29                           struct DisplaySurface *new_surface)
  30{
  31    egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
  32
  33    edpy->ds = new_surface;
  34}
  35
  36static void egl_scanout_disable(DisplayChangeListener *dcl)
  37{
  38    egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
  39
  40    egl_fb_destroy(&edpy->guest_fb);
  41    egl_fb_destroy(&edpy->blit_fb);
  42}
  43
  44static void egl_scanout_texture(DisplayChangeListener *dcl,
  45                                uint32_t backing_id,
  46                                bool backing_y_0_top,
  47                                uint32_t backing_width,
  48                                uint32_t backing_height,
  49                                uint32_t x, uint32_t y,
  50                                uint32_t w, uint32_t h)
  51{
  52    egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
  53
  54    edpy->y_0_top = backing_y_0_top;
  55
  56    /* source framebuffer */
  57    egl_fb_create_for_tex(&edpy->guest_fb,
  58                          backing_width, backing_height, backing_id);
  59
  60    /* dest framebuffer */
  61    if (edpy->blit_fb.width  != backing_width ||
  62        edpy->blit_fb.height != backing_height) {
  63        egl_fb_destroy(&edpy->blit_fb);
  64        egl_fb_create_new_tex(&edpy->blit_fb, backing_width, backing_height);
  65    }
  66}
  67
  68static void egl_scanout_flush(DisplayChangeListener *dcl,
  69                              uint32_t x, uint32_t y,
  70                              uint32_t w, uint32_t h)
  71{
  72    egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
  73
  74    if (!edpy->guest_fb.texture || !edpy->ds) {
  75        return;
  76    }
  77    assert(surface_width(edpy->ds)  == edpy->guest_fb.width);
  78    assert(surface_height(edpy->ds) == edpy->guest_fb.height);
  79    assert(surface_format(edpy->ds) == PIXMAN_x8r8g8b8);
  80
  81    egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top);
  82    egl_fb_read(surface_data(edpy->ds), &edpy->blit_fb);
  83
  84    dpy_gfx_update(edpy->dcl.con, x, y, w, h);
  85}
  86
  87static const DisplayChangeListenerOps egl_ops = {
  88    .dpy_name                = "egl-headless",
  89    .dpy_refresh             = egl_refresh,
  90    .dpy_gfx_update          = egl_gfx_update,
  91    .dpy_gfx_switch          = egl_gfx_switch,
  92
  93    .dpy_gl_ctx_create       = qemu_egl_create_context,
  94    .dpy_gl_ctx_destroy      = qemu_egl_destroy_context,
  95    .dpy_gl_ctx_make_current = qemu_egl_make_context_current,
  96    .dpy_gl_ctx_get_current  = qemu_egl_get_current_context,
  97
  98    .dpy_gl_scanout_disable  = egl_scanout_disable,
  99    .dpy_gl_scanout_texture  = egl_scanout_texture,
 100    .dpy_gl_update           = egl_scanout_flush,
 101};
 102
 103void egl_headless_init(void)
 104{
 105    QemuConsole *con;
 106    egl_dpy *edpy;
 107    int idx;
 108
 109    if (egl_rendernode_init(NULL) < 0) {
 110        error_report("egl: render node init failed");
 111        exit(1);
 112    }
 113
 114    for (idx = 0;; idx++) {
 115        con = qemu_console_lookup_by_index(idx);
 116        if (!con || !qemu_console_is_graphic(con)) {
 117            break;
 118        }
 119
 120        edpy = g_new0(egl_dpy, 1);
 121        edpy->dcl.con = con;
 122        edpy->dcl.ops = &egl_ops;
 123        register_displaychangelistener(&edpy->dcl);
 124    }
 125}
 126