Skip to content

Commit

Permalink
ui: split the GL context in a different object
Browse files Browse the repository at this point in the history
This will allow to have one GL context but a variable number of
listeners.

Signed-off-by: Marc-André Lureau <[email protected]>
Acked-by: Gerd Hoffmann <[email protected]>
  • Loading branch information
elmarco committed Dec 21, 2021
1 parent 7cc712e commit 5e79d51
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 76 deletions.
34 changes: 22 additions & 12 deletions include/ui/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ typedef struct QemuDmaBuf {
} QemuDmaBuf;

typedef struct DisplayState DisplayState;
typedef struct DisplayGLCtx DisplayGLCtx;

typedef struct DisplayChangeListenerOps {
const char *dpy_name;
Expand Down Expand Up @@ -213,16 +214,6 @@ typedef struct DisplayChangeListenerOps {
void (*dpy_cursor_define)(DisplayChangeListener *dcl,
QEMUCursor *cursor);

/* required if GL */
QEMUGLContext (*dpy_gl_ctx_create)(DisplayChangeListener *dcl,
QEMUGLParams *params);
/* required if GL */
void (*dpy_gl_ctx_destroy)(DisplayChangeListener *dcl,
QEMUGLContext ctx);
/* required if GL */
int (*dpy_gl_ctx_make_current)(DisplayChangeListener *dcl,
QEMUGLContext ctx);

/* required if GL */
void (*dpy_gl_scanout_disable)(DisplayChangeListener *dcl);
/* required if GL */
Expand Down Expand Up @@ -263,6 +254,26 @@ struct DisplayChangeListener {
QLIST_ENTRY(DisplayChangeListener) next;
};

typedef struct DisplayGLCtxOps {
/*
* We only check if the GLCtx is compatible with a DCL via ops. A natural
* evolution of this would be a callback to check some runtime requirements
* and allow various DCL kinds.
*/
const DisplayChangeListenerOps *compatible_dcl;

QEMUGLContext (*dpy_gl_ctx_create)(DisplayGLCtx *dgc,
QEMUGLParams *params);
void (*dpy_gl_ctx_destroy)(DisplayGLCtx *dgc,
QEMUGLContext ctx);
int (*dpy_gl_ctx_make_current)(DisplayGLCtx *dgc,
QEMUGLContext ctx);
} DisplayGLCtxOps;

struct DisplayGLCtx {
const DisplayGLCtxOps *ops;
};

DisplayState *init_displaystate(void);
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
pixman_format_code_t format,
Expand Down Expand Up @@ -409,8 +420,7 @@ void graphic_hw_gl_block(QemuConsole *con, bool block);

void qemu_console_early_init(void);

void qemu_console_set_display_gl_ctx(QemuConsole *con,
DisplayChangeListener *dcl);
void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *ctx);

QemuConsole *qemu_console_lookup_by_index(unsigned int index);
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);
Expand Down
6 changes: 3 additions & 3 deletions include/ui/egl-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include "ui/console.h"
#include "ui/egl-helpers.h"

QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl,
QEMUGLContext qemu_egl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params);
void qemu_egl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx);
int qemu_egl_make_context_current(DisplayChangeListener *dcl,
void qemu_egl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx);
int qemu_egl_make_context_current(DisplayGLCtx *dgc,
QEMUGLContext ctx);

#endif /* EGL_CONTEXT_H */
11 changes: 6 additions & 5 deletions include/ui/gtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef struct GtkDisplayState GtkDisplayState;

typedef struct VirtualGfxConsole {
GtkWidget *drawing_area;
DisplayGLCtx dgc;
DisplayChangeListener dcl;
QKbdState *kbd;
DisplaySurface *ds;
Expand Down Expand Up @@ -165,7 +166,7 @@ void gd_egl_update(DisplayChangeListener *dcl,
void gd_egl_refresh(DisplayChangeListener *dcl);
void gd_egl_switch(DisplayChangeListener *dcl,
DisplaySurface *surface);
QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl,
QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params);
void gd_egl_scanout_disable(DisplayChangeListener *dcl);
void gd_egl_scanout_texture(DisplayChangeListener *dcl,
Expand All @@ -187,7 +188,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
void gd_egl_scanout_flush(DisplayChangeListener *dcl,
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
void gtk_egl_init(DisplayGLMode mode);
int gd_egl_make_current(DisplayChangeListener *dcl,
int gd_egl_make_current(DisplayGLCtx *dgc,
QEMUGLContext ctx);

/* ui/gtk-gl-area.c */
Expand All @@ -198,9 +199,9 @@ void gd_gl_area_update(DisplayChangeListener *dcl,
void gd_gl_area_refresh(DisplayChangeListener *dcl);
void gd_gl_area_switch(DisplayChangeListener *dcl,
DisplaySurface *surface);
QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl,
QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params);
void gd_gl_area_destroy_context(DisplayChangeListener *dcl,
void gd_gl_area_destroy_context(DisplayGLCtx *dgc,
QEMUGLContext ctx);
void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf);
Expand All @@ -215,7 +216,7 @@ void gd_gl_area_scanout_disable(DisplayChangeListener *dcl);
void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
uint32_t x, uint32_t y, uint32_t w, uint32_t h);
void gtk_gl_area_init(void);
int gd_gl_area_make_current(DisplayChangeListener *dcl,
int gd_gl_area_make_current(DisplayGLCtx *dgc,
QEMUGLContext ctx);

/* gtk-clipboard.c */
Expand Down
7 changes: 4 additions & 3 deletions include/ui/sdl2.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#endif

struct sdl2_console {
DisplayGLCtx dgc;
DisplayChangeListener dcl;
DisplaySurface *surface;
DisplayOptions *opts;
Expand Down Expand Up @@ -65,10 +66,10 @@ void sdl2_gl_switch(DisplayChangeListener *dcl,
void sdl2_gl_refresh(DisplayChangeListener *dcl);
void sdl2_gl_redraw(struct sdl2_console *scon);

QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl,
QEMUGLContext sdl2_gl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params);
void sdl2_gl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx);
int sdl2_gl_make_context_current(DisplayChangeListener *dcl,
void sdl2_gl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx);
int sdl2_gl_make_context_current(DisplayGLCtx *dgc,
QEMUGLContext ctx);

void sdl2_gl_scanout_disable(DisplayChangeListener *dcl);
Expand Down
1 change: 1 addition & 0 deletions include/ui/spice-display.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ typedef struct SimpleSpiceCursor SimpleSpiceCursor;

struct SimpleSpiceDisplay {
DisplaySurface *ds;
DisplayGLCtx dgc;
DisplayChangeListener dcl;
void *buf;
int bufsize;
Expand Down
26 changes: 16 additions & 10 deletions ui/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct QemuConsole {
DisplayState *ds;
DisplaySurface *surface;
int dcls;
DisplayChangeListener *gl;
DisplayGLCtx *gl;
int gl_block;
QEMUTimer *gl_unblock_timer;
int window_id;
Expand Down Expand Up @@ -1458,17 +1458,24 @@ static bool dpy_compatible_with(QemuConsole *con,
return true;
}

void qemu_console_set_display_gl_ctx(QemuConsole *con,
DisplayChangeListener *dcl)
void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *gl)
{
/* display has opengl support */
assert(dcl->con);
if (dcl->con->gl) {
fprintf(stderr, "can't register two opengl displays (%s, %s)\n",
dcl->ops->dpy_name, dcl->con->gl->ops->dpy_name);
assert(con);
if (con->gl) {
error_report("The console already has an OpenGL context.");
exit(1);
}
dcl->con->gl = dcl;
con->gl = gl;
}

static bool dpy_gl_compatible_with(QemuConsole *con, DisplayChangeListener *dcl)
{
if (!con->gl) {
return true;
}

return con->gl->ops->compatible_dcl == dcl->ops;
}

void register_displaychangelistener(DisplayChangeListener *dcl)
Expand All @@ -1480,8 +1487,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl)

assert(!dcl->ds);

if (dcl->con && dcl->con->gl &&
dcl->con->gl != dcl) {
if (dcl->con && !dpy_gl_compatible_with(dcl->con, dcl)) {
error_report("Display %s is incompatible with the GL context",
dcl->ops->dpy_name);
exit(1);
Expand Down
6 changes: 3 additions & 3 deletions ui/egl-context.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "qemu/osdep.h"
#include "ui/egl-context.h"

QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl,
QEMUGLContext qemu_egl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
EGLContext ctx;
Expand All @@ -24,12 +24,12 @@ QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl,
return ctx;
}

void qemu_egl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx)
void qemu_egl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx)
{
eglDestroyContext(qemu_egl_display, ctx);
}

int qemu_egl_make_context_current(DisplayChangeListener *dcl,
int qemu_egl_make_context_current(DisplayGLCtx *dgc,
QEMUGLContext ctx)
{
return eglMakeCurrent(qemu_egl_display,
Expand Down
21 changes: 14 additions & 7 deletions ui/egl-headless.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ static void egl_gfx_switch(DisplayChangeListener *dcl,
edpy->ds = new_surface;
}

static QEMUGLContext egl_create_context(DisplayChangeListener *dcl,
static QEMUGLContext egl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
qemu_egl_rn_ctx);
return qemu_egl_create_context(dcl, params);
return qemu_egl_create_context(dgc, params);
}

static void egl_scanout_disable(DisplayChangeListener *dcl)
Expand Down Expand Up @@ -157,10 +157,6 @@ static const DisplayChangeListenerOps egl_ops = {
.dpy_gfx_update = egl_gfx_update,
.dpy_gfx_switch = egl_gfx_switch,

.dpy_gl_ctx_create = egl_create_context,
.dpy_gl_ctx_destroy = qemu_egl_destroy_context,
.dpy_gl_ctx_make_current = qemu_egl_make_context_current,

.dpy_gl_scanout_disable = egl_scanout_disable,
.dpy_gl_scanout_texture = egl_scanout_texture,
.dpy_gl_scanout_dmabuf = egl_scanout_dmabuf,
Expand All @@ -170,6 +166,13 @@ static const DisplayChangeListenerOps egl_ops = {
.dpy_gl_update = egl_scanout_flush,
};

static const DisplayGLCtxOps eglctx_ops = {
.compatible_dcl = &egl_ops,
.dpy_gl_ctx_create = egl_create_context,
.dpy_gl_ctx_destroy = qemu_egl_destroy_context,
.dpy_gl_ctx_make_current = qemu_egl_make_context_current,
};

static void early_egl_headless_init(DisplayOptions *opts)
{
display_opengl = 1;
Expand All @@ -188,6 +191,8 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts)
}

for (idx = 0;; idx++) {
DisplayGLCtx *ctx;

con = qemu_console_lookup_by_index(idx);
if (!con || !qemu_console_is_graphic(con)) {
break;
Expand All @@ -197,7 +202,9 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts)
edpy->dcl.con = con;
edpy->dcl.ops = &egl_ops;
edpy->gls = qemu_gl_init_shader();
qemu_console_set_display_gl_ctx(con, &edpy->dcl);
ctx = g_new0(DisplayGLCtx, 1);
ctx->ops = &eglctx_ops;
qemu_console_set_display_gl_ctx(con, ctx);
register_displaychangelistener(&edpy->dcl);
}
}
Expand Down
10 changes: 5 additions & 5 deletions ui/gtk-egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,14 @@ void gd_egl_switch(DisplayChangeListener *dcl,
}
}

QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl,
QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc);

eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
vc->gfx.esurface, vc->gfx.ectx);
return qemu_egl_create_context(dcl, params);
return qemu_egl_create_context(dgc, params);
}

void gd_egl_scanout_disable(DisplayChangeListener *dcl)
Expand Down Expand Up @@ -360,10 +360,10 @@ void gtk_egl_init(DisplayGLMode mode)
display_opengl = 1;
}

int gd_egl_make_current(DisplayChangeListener *dcl,
int gd_egl_make_current(DisplayGLCtx *dgc,
QEMUGLContext ctx)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc);

return eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
vc->gfx.esurface, ctx);
Expand Down
8 changes: 4 additions & 4 deletions ui/gtk-gl-area.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ void gd_gl_area_switch(DisplayChangeListener *dcl,
}
}

QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl,
QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc);
GdkWindow *window;
GdkGLContext *ctx;
GError *err = NULL;
Expand All @@ -199,7 +199,7 @@ QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl,
return ctx;
}

void gd_gl_area_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx)
void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx)
{
/* FIXME */
}
Expand Down Expand Up @@ -278,7 +278,7 @@ void gtk_gl_area_init(void)
display_opengl = 1;
}

int gd_gl_area_make_current(DisplayChangeListener *dcl,
int gd_gl_area_make_current(DisplayGLCtx *dgc,
QEMUGLContext ctx)
{
gdk_gl_context_make_current(ctx);
Expand Down
Loading

0 comments on commit 5e79d51

Please sign in to comment.