@@ -34,7 +34,7 @@ extern int qemu_egl_rn_fd;
extern struct gbm_device *qemu_egl_rn_gbm_dev;
extern EGLContext qemu_egl_rn_ctx;
-int egl_rendernode_init(const char *rendernode);
+int egl_rendernode_init(const char *rendernode, bool gles);
int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc);
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
@@ -45,7 +45,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win);
int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy);
-int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy);
-EGLContext qemu_egl_init_ctx(void);
+int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, bool gles);
+EGLContext qemu_egl_init_ctx(bool gles);
#endif /* EGL_HELPERS_H */
@@ -1242,6 +1242,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
"-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]\n"
" [,window_close=on|off][,gl=on|core|es|off]\n"
"-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n"
+ "-display egl-headless[,gl=core|es]|\n"
"-display vnc=<display>[,<optargs>]\n"
"-display curses\n"
"-display none"
@@ -175,7 +175,7 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts)
egl_dpy *edpy;
int idx;
- if (egl_rendernode_init(NULL) < 0) {
+ if (egl_rendernode_init(NULL, opts->gl == DISPLAYGL_MODE_ES) < 0) {
error_report("egl: render node init failed");
exit(1);
}
@@ -191,7 +191,7 @@ static int qemu_egl_rendernode_open(const char *rendernode)
return fd;
}
-int egl_rendernode_init(const char *rendernode)
+int egl_rendernode_init(const char *rendernode, bool gles)
{
qemu_egl_rn_fd = -1;
int rc;
@@ -208,7 +208,8 @@ int egl_rendernode_init(const char *rendernode)
goto err;
}
- rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev);
+ rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev,
+ gles);
if (rc != 0) {
/* qemu_egl_init_dpy_mesa reports error */
goto err;
@@ -225,7 +226,7 @@ int egl_rendernode_init(const char *rendernode)
goto err;
}
- qemu_egl_rn_ctx = qemu_egl_init_ctx();
+ qemu_egl_rn_ctx = qemu_egl_init_ctx(gles);
if (!qemu_egl_rn_ctx) {
error_report("egl: egl_init_ctx failed");
goto err;
@@ -392,7 +393,8 @@ static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
}
static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
- EGLenum platform)
+ EGLenum platform,
+ bool gles)
{
static const EGLint conf_att_gl[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
@@ -403,6 +405,15 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
EGL_ALPHA_SIZE, 0,
EGL_NONE,
};
+ static const EGLint conf_att_gles[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 5,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, 0,
+ EGL_NONE,
+ };
EGLint major, minor;
EGLBoolean b;
EGLint n;
@@ -419,14 +430,21 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
return -1;
}
- b = eglBindAPI(EGL_OPENGL_API);
+ if (gles)
+ b = eglBindAPI(EGL_OPENGL_ES_API);
+ else
+ b = eglBindAPI(EGL_OPENGL_API);
if (b == EGL_FALSE) {
error_report("egl: eglBindAPI failed");
return -1;
}
- b = eglChooseConfig(qemu_egl_display, conf_att_gl,
- &qemu_egl_config, 1, &n);
+ if (gles)
+ b = eglChooseConfig(qemu_egl_display, conf_att_gles,
+ &qemu_egl_config, 1, &n);
+ else
+ b = eglChooseConfig(qemu_egl_display, conf_att_gl,
+ &qemu_egl_config, 1, &n);
if (b == EGL_FALSE || n != 1) {
error_report("egl: eglChooseConfig failed");
return -1;
@@ -437,32 +455,40 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy)
{
#ifdef EGL_KHR_platform_x11
- return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR);
+ return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR, false);
#else
- return qemu_egl_init_dpy(dpy, 0);
+ return qemu_egl_init_dpy(dpy, 0, false);
#endif
}
-int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy)
+int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, bool gles)
{
#ifdef EGL_MESA_platform_gbm
- return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA);
+ return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA, gles);
#else
- return qemu_egl_init_dpy(dpy, 0);
+ return qemu_egl_init_dpy(dpy, 0, gles);
#endif
}
-EGLContext qemu_egl_init_ctx(void)
+EGLContext qemu_egl_init_ctx(bool gles)
{
static const EGLint ctx_att_gl[] = {
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
EGL_NONE
};
+ static const EGLint ctx_att_gles[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
EGLContext ectx;
EGLBoolean b;
- ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
- ctx_att_gl);
+ if (gles)
+ ectx = eglCreateContext(qemu_egl_display, qemu_egl_config,
+ EGL_NO_CONTEXT, ctx_att_gles);
+ else
+ ectx = eglCreateContext(qemu_egl_display, qemu_egl_config,
+ EGL_NO_CONTEXT, ctx_att_gl);
if (ectx == EGL_NO_CONTEXT) {
error_report("egl: eglCreateContext failed");
return NULL;
@@ -57,7 +57,7 @@ void gd_egl_init(VirtualConsole *vc)
return;
}
- vc->gfx.ectx = qemu_egl_init_ctx();
+ vc->gfx.ectx = qemu_egl_init_ctx(false);
vc->gfx.esurface = qemu_egl_init_surface_x11(vc->gfx.ectx, x11_window);
assert(vc->gfx.esurface);
@@ -829,7 +829,7 @@ void qemu_spice_init(void)
"incompatible with -spice port/tls-port");
exit(1);
}
- if (egl_rendernode_init(qemu_opt_get(opts, "rendernode")) != 0) {
+ if (egl_rendernode_init(qemu_opt_get(opts, "rendernode"), false) != 0) {
error_report("Failed to initialize EGL render node for SPICE GL");
exit(1);
}
This will be mainly useful for automated testing of virglrenderer on ES. Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> --- include/ui/egl-helpers.h | 6 ++--- qemu-options.hx | 1 + ui/egl-headless.c | 2 +- ui/egl-helpers.c | 56 +++++++++++++++++++++++++++++----------- ui/gtk-egl.c | 2 +- ui/spice-core.c | 2 +- 6 files changed, 48 insertions(+), 21 deletions(-)