[PATCH 2/3] Add wayland egl support for vo_gl

Alexander Preisinger alexander.preisinger at gmail.com
Thu Aug 23 23:08:23 PDT 2012


---
 libvo/gl_common.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libvo/gl_common.h |   9 +++
 2 files changed, 208 insertions(+)

diff --git a/libvo/gl_common.c b/libvo/gl_common.c
index 3b72349..d916db7 100644
--- a/libvo/gl_common.c
+++ b/libvo/gl_common.c
@@ -1971,6 +1971,182 @@ static void swapGlBuffers_x11(MPGLContext *ctx)
 }
 #endif
 
+#ifdef CONFIG_GL_WAYLAND
+#include <assert.h>
+#include "wl_common.h"
+
+static struct wl_priv wl = {NULL, NULL, NULL, NULL};
+    /* New wl_common requires to preset it
+        to zero, but that is a bit too hackish for my taste.
+        Maybe there is another way to get around the fact that mplayer calls
+        vo_init two times. */
+
+struct vo_wl_private {
+    EGLSurface egl_surface;
+
+    struct {
+        EGLDisplay dpy;
+        EGLContext ctx;
+        EGLConfig conf;
+    } egl;
+};
+
+static void appendstr(char **dst, const char *str)
+{
+    int newsize;
+    char *newstr;
+    if (!str)
+        return;
+    newsize = strlen(*dst) + 1 + strlen(str) + 1;
+    newstr = realloc(*dst, newsize);
+    if (!newstr)
+        return;
+    *dst = newstr;
+    strcat(*dst, " ");
+    strcat(*dst, str);
+}
+
+static int init_wayland(struct vo *vo)
+{
+    wl.vo = vo;
+    return vo_wl_priv_init(&wl);
+}
+
+static int create_window_wayland(struct MPGLContext *ctx, uint32_t d_width,
+                                 uint32_t d_height, uint32_t flags)
+{
+    wl.window->width = d_width;
+    wl.window->height = d_height;
+
+    if (!wl.window)
+        return 0;
+
+    if (!wl.window->private) {
+        wl.window->private = malloc(sizeof(struct vo_wl_private));
+
+        wl.window->private->egl.dpy = eglGetDisplay(wl.display->display);
+        assert(wl.window->private->egl.dpy);
+
+        wl.window->egl_window = wl_egl_window_create(wl.window->surface,
+                wl.window->width, wl.window->height);
+
+        wl.window->x = wl.display->pos_x;
+        wl.window->y = wl.display->pos_y;
+    }
+
+    return 1;
+}
+
+static int setGlWindow_wayland(MPGLContext *ctx)
+{
+    GL *gl = ctx->gl;
+    void *(*getProcAddress)(const GLubyte *);
+    const char *(*eglExtStr)(EGLDisplay *, int);
+    char *eglstr = strdup("");
+
+    EGLint config_attribs[] = {
+        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+        EGL_RED_SIZE, 1,
+        EGL_GREEN_SIZE, 1,
+        EGL_BLUE_SIZE, 1,
+        EGL_ALPHA_SIZE, 0,
+        EGL_DEPTH_SIZE, 1,
+        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+        EGL_NONE
+    };
+
+    EGLint major, minor, n;
+    EGLBoolean ret;
+
+    ret = eglInitialize(wl.window->private->egl.dpy, &major, &minor);
+    assert(ret == EGL_TRUE);
+
+    ret = eglBindAPI(EGL_OPENGL_API);
+    assert(ret == EGL_TRUE);
+
+    ret = eglChooseConfig(wl.window->private->egl.dpy, config_attribs,
+                  &wl.window->private->egl.conf, 1, &n);
+    assert(ret && n == 1);
+
+    wl.window->private->egl.ctx = eglCreateContext(
+            wl.window->private->egl.dpy,
+            wl.window->private->egl.conf,
+            EGL_NO_CONTEXT, NULL);
+    assert(wl.window->private->egl.ctx);
+
+    wl.window->private->egl_surface = eglCreateWindowSurface(
+            wl.window->private->egl.dpy, wl.window->private->egl.conf,
+            wl.window->egl_window, NULL);
+
+    ret = eglMakeCurrent(wl.window->private->egl.dpy,
+            wl.window->private->egl_surface,
+            wl.window->private->egl_surface,
+            wl.window->private->egl.ctx);
+
+    assert(ret == EGL_TRUE);
+
+    getProcAddress = getdladdr("eglGetProcAddress");
+    if (!getProcAddress)
+        mp_msg(MSGT_VO, MSGL_WARN, "[egl] No eglGetProcAdress");
+
+    eglExtStr = getdladdr("eglQueryString");
+    if (eglExtStr)
+        appendstr(&eglstr,
+                eglExtStr(wl.window->private->egl.dpy, EGL_EXTENSIONS));
+
+    getFunctions(gl, (void *(*)(const GLubyte*))eglGetProcAddress, eglstr);
+    if (!gl->BindProgram)
+        getFunctions(gl, NULL, eglstr);
+
+    wl_display_roundtrip(wl.display->display);
+
+    return SET_WINDOW_OK;
+}
+
+static void update_xinerama_info_wayland(struct vo * vo)
+{
+    struct MPOpts *opts = vo->opts;
+
+    vo_wl_priv_init(&wl);
+
+    while (!wl.display->mode_received)
+        wl_display_roundtrip(wl.display->display);
+
+    opts->vo_screenwidth = wl.display->output_width;
+    opts->vo_screenheight = wl.display->output_height;
+
+    aspect_save_screenres(vo, opts->vo_screenwidth, opts->vo_screenheight);
+}
+
+static void releaseGlContext_wayland(MPGLContext *ctx)
+{
+    GL *gl = ctx->gl;
+    gl->Finish();
+    eglMakeCurrent(wl.window->private->egl.dpy, NULL, NULL, EGL_NO_CONTEXT);
+    eglDestroyContext(wl.window->private->egl.dpy,
+            wl.window->private->egl.ctx);
+    eglTerminate(wl.window->private->egl.dpy);
+}
+
+static void swapGlBuffers_wayland(MPGLContext *ctx)
+{
+    eglSwapBuffers(wl.window->private->egl.dpy,
+            wl.window->private->egl_surface);
+    wl_display_flush(wl.display->display);
+}
+
+void fullscreen_wayland(struct vo *vo)
+{
+    vo_wl_priv_fullscreen(&wl);
+}
+
+int check_events_wayland(struct vo *vo)
+{
+    return vo_wl_priv_check_events(&wl);
+}
+
+#endif
+
 #ifdef CONFIG_GL_SDL
 #include "sdl_common.h"
 
@@ -2037,6 +2213,9 @@ MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo)
         ctx = init_mpglcontext(GLTYPE_X11, vo);
         if (ctx)
             return ctx;
+        ctx = init_mpglcontext(GLTYPE_WAYLAND, vo);
+        if (ctx)
+            return ctx;
         return init_mpglcontext(GLTYPE_SDL, vo);
     }
     ctx = talloc_zero(NULL, MPGLContext);
@@ -2090,6 +2269,21 @@ MPGLContext *init_mpglcontext(enum MPGLType type, struct vo *vo)
             return ctx;
         break;
 #endif
+#ifdef CONFIG_GL_WAYLAND
+    case GLTYPE_WAYLAND:
+        ctx->create_window = create_window_wayland;
+        ctx->setGlWindow = setGlWindow_wayland;
+        ctx->releaseGlContext = releaseGlContext_wayland;
+        ctx->swapGlBuffers = swapGlBuffers_wayland;
+        ctx->update_xinerama_info = update_xinerama_info_wayland;
+        ctx->border = vo_wl_border;
+        ctx->check_events = check_events_wayland;
+        ctx->fullscreen = fullscreen_wayland;
+        ctx->ontop = vo_wl_ontop;
+        if (init_wayland(vo))
+            return ctx;
+        break;
+#endif
 #ifdef CONFIG_GL_SDL
     case GLTYPE_SDL:
         ctx->create_window = create_window_sdl;
@@ -2131,6 +2325,11 @@ void uninit_mpglcontext(MPGLContext *ctx)
         vo_x11_uninit(ctx->vo);
         break;
 #endif
+#ifdef CONFIG_GL_WAYLAND
+    case GLTYPE_WAYLAND:
+        vo_wl_priv_uninit(&wl);
+        break;
+#endif
 #ifdef CONFIG_GL_SDL
     case GLTYPE_SDL:
         vo_sdl_uninit();
diff --git a/libvo/gl_common.h b/libvo/gl_common.h
index 46a91e2..793f3f3 100644
--- a/libvo/gl_common.h
+++ b/libvo/gl_common.h
@@ -48,6 +48,14 @@
 #if defined(CONFIG_GL_COCOA) && !defined(CONFIG_GL_X11)
 #include <OpenGL/gl.h>
 #else
+
+#ifdef CONFIG_GL_WAYLAND
+#include "wl_common.h"
+#include <wayland-egl.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#endif
+
 #include <GL/gl.h>
 #endif
 
@@ -371,6 +379,7 @@ enum MPGLType {
     GLTYPE_W32,
     GLTYPE_X11,
     GLTYPE_SDL,
+    GLTYPE_WAYLAND,
 };
 
 typedef struct MPGLContext {
-- 
1.7.12



More information about the wayland-devel mailing list