From: Max Reitz <mreitz@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 3/4] ui: add egl-helpers
Date: Wed, 20 May 2015 14:15:29 +0200 [thread overview]
Message-ID: <555C7AE1.7090204@redhat.com> (raw)
In-Reply-To: <1432045761-15543-4-git-send-email-kraxel@redhat.com>
On 19.05.2015 16:29, Gerd Hoffmann wrote:
> Add helper functions to initialize OpenGL using egl.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
> configure | 2 +-
> include/ui/egl-helpers.h | 16 ++++++
> ui/Makefile.objs | 3 +
> ui/egl-helpers.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 163 insertions(+), 1 deletion(-)
> create mode 100644 include/ui/egl-helpers.h
> create mode 100644 ui/egl-helpers.c
>
> diff --git a/configure b/configure
> index df1048a..e0e6b54 100755
> --- a/configure
> +++ b/configure
> @@ -3153,7 +3153,7 @@ else
> fi
>
> if test "$opengl" != "no" ; then
> - opengl_pkgs="gl glesv2 epoxy"
> + opengl_pkgs="gl glesv2 epoxy egl"
> if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then
> opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
> opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
> diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
> new file mode 100644
> index 0000000..5ad5dc3
> --- /dev/null
> +++ b/include/ui/egl-helpers.h
> @@ -0,0 +1,16 @@
> +#ifndef EGL_HELPERS_H
> +#define EGL_HELPERS_H
> +
> +#include <epoxy/gl.h>
> +#include <epoxy/egl.h>
> +
> +extern EGLDisplay *qemu_egl_display;
> +extern EGLConfig qemu_egl_config;
> +
> +EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win);
> +
> +int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug);
> +EGLContext qemu_egl_init_ctx(void);
> +bool qemu_egl_has_ext(const char *haystack, const char *needle);
> +
> +#endif /* EGL_HELPERS_H */
> diff --git a/ui/Makefile.objs b/ui/Makefile.objs
> index 029a42a..5c46870 100644
> --- a/ui/Makefile.objs
> +++ b/ui/Makefile.objs
> @@ -30,11 +30,14 @@ sdl.mo-cflags := $(SDL_CFLAGS)
> ifeq ($(CONFIG_OPENGL),y)
> common-obj-y += shader.o
> common-obj-y += console-gl.o
> +common-obj-y += egl-helpers.o
> endif
>
> gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
> shader.o-cflags += $(OPENGL_CFLAGS)
> console-gl.o-cflags += $(OPENGL_CFLAGS)
> +egl-helpers.o-cflags += $(OPENGL_CFLAGS)
>
> shader.o-libs += $(OPENGL_LIBS)
> console-gl.o-libs += $(OPENGL_LIBS)
> +egl-helpers.o-libs += $(OPENGL_LIBS)
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> new file mode 100644
> index 0000000..4dcca38
> --- /dev/null
> +++ b/ui/egl-helpers.c
> @@ -0,0 +1,143 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <glob.h>
> +
> +#include "ui/egl-helpers.h"
> +
> +EGLDisplay *qemu_egl_display;
> +EGLConfig qemu_egl_config;
> +
> +/* ---------------------------------------------------------------------- */
> +
> +static int egl_debug;
> +
> +#define egl_dbg(_x ...) \
> + do { \
> + if (egl_debug) { \
> + fprintf(stderr, "egl: " _x); \
> + } \
> + } while (0);
> +
> +/* ---------------------------------------------------------------------- */
> +
> +EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
> +{
> + EGLSurface esurface;
> + EGLBoolean b;
> +
> + egl_dbg("eglCreateWindowSurface (x11 win id 0x%lx) ...\n",
> + (unsigned long) win);
> + esurface = eglCreateWindowSurface(qemu_egl_display,
> + qemu_egl_config,
> + (EGLNativeWindowType)win, NULL);
> + if (!esurface) {
Since I don't have any insights into EGL other than looking up the
functions online, all I can do is nitpick:
The spec says it's EGL_NO_SURFACE (which probably is 0/NULL, but anyway...).
> + fprintf(stderr, "egl: eglCreateWindowSurface failed\n");
> + return NULL;
> + }
> +
> + b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
> + if (!b) {
EGL_FALSE, but assuming that is 0 is pretty reasonable, I guess. :-)
> + fprintf(stderr, "egl: eglMakeCurrent failed\n");
> + return NULL;
> + }
> +
> + return esurface;
> +}
> +
> +/* ---------------------------------------------------------------------- */
> +
> +int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
> +{
> + static const EGLint conf_att_gl[] = {
> + EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
> + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
> + EGL_RED_SIZE, 1,
> + EGL_GREEN_SIZE, 1,
> + EGL_BLUE_SIZE, 1,
Wouldn't it be more like 5, 6, 5? Apparently it doesn't really matter
whether one specifies 1 or e.g. 5, as long as there is a configuration
with equal to or more than 5 bits; but we won't be able to work with
less than 5/6/5 anyway...
> + 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, 1,
> + EGL_GREEN_SIZE, 1,
> + EGL_BLUE_SIZE, 1,
> + EGL_ALPHA_SIZE, 0,
> + EGL_NONE,
> + };
> + EGLint major, minor;
> + EGLBoolean b;
> + EGLint n;
> +
> + if (debug) {
> + egl_debug = 1;
> + setenv("EGL_LOG_LEVEL", "debug", true);
> + setenv("LIBGL_DEBUG", "verbose", true);
> + }
> +
> + egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
> + qemu_egl_display = eglGetDisplay(dpy);
> + if (!qemu_egl_display) {
EGL_NO_DISPLAY
> + fprintf(stderr, "egl: eglGetDisplay failed\n");
> + return -1;
> + }
> +
> + egl_dbg("eglInitialize ...\n");
> + b = eglInitialize(qemu_egl_display, &major, &minor);
> + if (!b) {
> + fprintf(stderr, "egl: eglInitialize failed\n");
> + return -1;
> + }
Should we care for eglTerminate() after this point (on error) or do we
just assume there's no hope on failure anyway?
> +
> + egl_dbg("eglBindAPI ...\n");
> + b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
> + if (!b) {
> + fprintf(stderr, "egl: eglBindAPI failed\n");
> + return -1;
> + }
> +
> + egl_dbg("eglChooseConfig ...\n");
> + b = eglChooseConfig(qemu_egl_display,
> + gles ? conf_att_gles : conf_att_gl,
> + &qemu_egl_config, 1, &n);
Well... It would be sad if the system actually supported true color
(like basically any system everywhere) and we get some 5/6/5
configuration here (or even worse). I do think it would be better to
actually receive the whole list and then scan through it to find the
best configuration; if you want to keep it this way, we probably really
have to make the attributes above reflect the minimum requirements
(5/6/5 for R/G/B bit sizes).
> + if (!b || n != 1) {
> + fprintf(stderr, "egl: eglChooseConfig failed\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +EGLContext qemu_egl_init_ctx(void)
> +{
> + static const EGLint ctx_att[] = {
> + EGL_CONTEXT_CLIENT_VERSION, 2,
> + EGL_NONE
> + };
> +
> + EGLContext ectx;
> + EGLBoolean b;
> +
> + egl_dbg("eglCreateContext ...\n");
> + ectx = eglCreateContext(qemu_egl_display, qemu_egl_config,
> + EGL_NO_CONTEXT, ctx_att);
The manpage says specifying EGL_CONTEXT_CLIENT_VERSION is only valid
when creating an OpenGL ES context.
> + if (!ectx) {
EGL_NO_CONTEXT :-)
> + fprintf(stderr, "egl: eglCreateContext failed\n");
> + return NULL;
> + }
> +
> + b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
What is this call for? So that some rudimentary OpenGL operations can be
executed which don't need access to a framebuffer?
Max
> + if (!b) {
> + fprintf(stderr, "egl: eglMakeCurrent failed\n");
> + return NULL;
> + }
> +
> + return ectx;
> +}
next prev parent reply other threads:[~2015-05-20 12:15 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-19 14:29 [Qemu-devel] [PATCH 0/4] gtk: add opengl support Gerd Hoffmann
2015-05-19 14:29 ` [Qemu-devel] [PATCH 1/4] ui: use libexpoxy Gerd Hoffmann
2015-05-20 10:47 ` Max Reitz
2015-05-19 14:29 ` [Qemu-devel] [PATCH 2/4] ui: shader.h protect against double inclusion Gerd Hoffmann
2015-05-20 10:58 ` Max Reitz
2015-05-19 14:29 ` [Qemu-devel] [PATCH 3/4] ui: add egl-helpers Gerd Hoffmann
2015-05-20 12:15 ` Max Reitz [this message]
2015-05-20 14:46 ` Gerd Hoffmann
2015-05-19 14:29 ` [Qemu-devel] [PATCH 4/4] gtk: add opengl support, using egl Gerd Hoffmann
2015-05-20 13:29 ` Max Reitz
2015-05-20 14:14 ` Gerd Hoffmann
2015-05-20 14:16 ` Max Reitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=555C7AE1.7090204@redhat.com \
--to=mreitz@redhat.com \
--cc=kraxel@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).