gtk: add opengl support, using egl

This adds opengl rendering support to the gtk ui, using egl.
It's off by default for now, use 'qemu -display gtk,gl=on'
to play with this.

Note that gtk got native opengl support with release 3.16.
There most likely will be a separate implementation for 3.16+,
using the native gtk opengl support.  This patch covers older
versions (and for the time being 3.16 too, hopefully without
rendering quirks).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2015-01-20 12:43:28 +01:00
parent 7ced9e9f6d
commit 97edf3bd5e
6 changed files with 253 additions and 17 deletions

View file

@ -339,7 +339,7 @@ static void gd_update_geometry_hints(VirtualConsole *vc)
gtk_window_set_geometry_hints(geo_window, geo_widget, &geo, mask);
}
static void gd_update_windowsize(VirtualConsole *vc)
void gd_update_windowsize(VirtualConsole *vc)
{
GtkDisplayState *s = vc->s;
@ -581,6 +581,33 @@ static void gd_switch(DisplayChangeListener *dcl,
}
}
static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "gtk",
.dpy_gfx_update = gd_update,
.dpy_gfx_switch = gd_switch,
.dpy_gfx_check_format = qemu_pixman_check_format,
.dpy_refresh = gd_refresh,
.dpy_mouse_set = gd_mouse_set,
.dpy_cursor_define = gd_cursor_define,
};
#if defined(CONFIG_OPENGL)
/** DisplayState Callbacks (opengl version) **/
static const DisplayChangeListenerOps dcl_egl_ops = {
.dpy_name = "gtk-egl",
.dpy_gfx_update = gd_egl_update,
.dpy_gfx_switch = gd_egl_switch,
.dpy_gfx_check_format = console_gl_check_format,
.dpy_refresh = gd_egl_refresh,
.dpy_mouse_set = gd_mouse_set,
.dpy_cursor_define = gd_cursor_define,
};
#endif
/** QEMU Events **/
static void gd_change_runstate(void *opaque, int running, RunState state)
@ -637,6 +664,13 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
int ww, wh;
int fbw, fbh;
#if defined(CONFIG_OPENGL)
if (vc->gfx.gls) {
gd_egl_draw(vc);
return TRUE;
}
#endif
if (!gtk_widget_get_realized(widget)) {
return FALSE;
}
@ -1676,16 +1710,6 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s)
return machine_menu;
}
static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "gtk",
.dpy_gfx_update = gd_update,
.dpy_gfx_switch = gd_switch,
.dpy_gfx_check_format = qemu_pixman_check_format,
.dpy_refresh = gd_refresh,
.dpy_mouse_set = gd_mouse_set,
.dpy_cursor_define = gd_cursor_define,
};
static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
QemuConsole *con, int idx,
GSList *group, GtkWidget *view_menu)
@ -1713,7 +1737,29 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
vc->tab_item, gtk_label_new(vc->label));
vc->gfx.dcl.ops = &dcl_ops;
#if defined(CONFIG_OPENGL)
if (display_opengl) {
/*
* gtk_widget_set_double_buffered() was deprecated in 3.14.
* It is required for opengl rendering on X11 though. A
* proper replacement (native opengl support) is only
* available in 3.16+. Silence the warning if possible.
*/
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE);
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
#pragma GCC diagnostic pop
#endif
vc->gfx.dcl.ops = &dcl_egl_ops;
} else
#endif
{
vc->gfx.dcl.ops = &dcl_ops;
}
vc->gfx.dcl.con = con;
register_displaychangelistener(&vc->gfx.dcl);
@ -1876,8 +1922,6 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
GtkDisplayState *s = g_malloc0(sizeof(*s));
char *filename;
gtk_init(NULL, NULL);
s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#if GTK_CHECK_VERSION(3, 2, 0)
s->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
@ -1954,8 +1998,24 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
gd_set_keycode_type(s);
}
void early_gtk_display_init(void)
void early_gtk_display_init(int opengl)
{
gtk_init(NULL, NULL);
switch (opengl) {
case -1: /* default */
case 0: /* off */
break;
case 1: /* on */
#if defined(CONFIG_OPENGL)
gtk_egl_init();
#endif
break;
default:
g_assert_not_reached();
break;
}
#if defined(CONFIG_VTE)
register_vc_handler(gd_vc_handler);
#endif