From a29a76dbabf8e68febc50288465fccdfd8d1313f Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 25 May 2011 01:37:56 +0100 Subject: [PATCH] Adds _cogl_wayland_texture_2d_new_from_buffer API This adds internal API to be able to wrap a wayland buffer as a CoglTexture2D. There is a --enable-wayland-egl-server option to decide if Cogl should support this feature and potentially any EGL based winsys could support this through the EGL_KHR_image_base and EGL_WL_bind_display extensions. --- cogl/cogl-display-private.h | 7 ++ cogl/cogl-display.c | 10 +++ cogl/cogl-display.h | 6 ++ cogl/cogl-internal.h | 5 +- cogl/cogl-texture-2d.c | 69 +++++++++++++++++++ cogl/cogl-texture-2d.h | 35 ++++++++++ .../cogl-winsys-egl-feature-functions.h | 11 +++ cogl/winsys/cogl-winsys-egl.c | 12 ++++ configure.ac | 16 +++++ 9 files changed, 169 insertions(+), 2 deletions(-) diff --git a/cogl/cogl-display-private.h b/cogl/cogl-display-private.h index 964dfb677..24118550b 100644 --- a/cogl/cogl-display-private.h +++ b/cogl/cogl-display-private.h @@ -29,6 +29,9 @@ #include "cogl-display.h" #include "cogl-renderer.h" #include "cogl-onscreen-template.h" +#if COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +#include +#endif struct _CoglDisplay { @@ -38,6 +41,10 @@ struct _CoglDisplay CoglRenderer *renderer; CoglOnscreenTemplate *onscreen_template; +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + struct wl_display *wayland_compositor_display; +#endif + #ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT struct gdl_plane *gdl_plane; #endif diff --git a/cogl/cogl-display.c b/cogl/cogl-display.c index 967c0706e..aea9d8d86 100644 --- a/cogl/cogl-display.c +++ b/cogl/cogl-display.c @@ -129,3 +129,13 @@ cogl_gdl_display_set_plane (CoglDisplay *display, } #endif +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +void +cogl_wayland_display_set_compositor_display (CoglDisplay *display, + struct wl_display *wayland_display) +{ + g_return_if_fail (display->setup == FALSE); + + display->wayland_compositor_display = wayland_display; +} +#endif diff --git a/cogl/cogl-display.h b/cogl/cogl-display.h index 720b86b2e..b12041bff 100644 --- a/cogl/cogl-display.h +++ b/cogl/cogl-display.h @@ -94,6 +94,12 @@ cogl_gdl_display_set_plane (CoglDisplay *display, struct gdl_plane *plane); #endif +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +void +cogl_wayland_display_set_compositor_display (CoglDisplay *display, + struct wl_display *wayland_display); +#endif + G_END_DECLS #endif /* __COGL_DISPLAY_H__ */ diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h index d9619e1f9..a1bb4007a 100644 --- a/cogl/cogl-internal.h +++ b/cogl/cogl-internal.h @@ -128,8 +128,9 @@ typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/ typedef enum { - COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0, - COGL_PRIVATE_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP = 1L<<1 + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0, + COGL_PRIVATE_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP = 1L<<1, + COGL_PRIVATE_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER = 1L<<2 } CoglPrivateFeatureFlags; gboolean diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 9f2e5506a..57a193a08 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -44,6 +44,10 @@ #include #include +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +#include +#endif + static void _cogl_texture_2d_free (CoglTexture2D *tex_2d); COGL_TEXTURE_DEFINE (Texture2D, texture_2d); @@ -541,6 +545,71 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx, } #endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */ +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +static CoglPixelFormat +get_buffer_format (struct wl_buffer *buffer) +{ + struct wl_compositor *compositor = buffer->compositor; + struct wl_visual *visual = buffer->visual; +#if G_BYTE_ORDER == G_BIG_ENDIAN + if (visual == &compositor->premultiplied_argb_visual) + return COGL_PIXEL_FORMAT_ARGB_8888_PRE; + else if (visual == &compositor->argb_visual) + return COGL_PIXEL_FORMAT_ARGB_8888; + else if (visual == &compositor->rgb_visual) + return COGL_PIXEL_FORMAT_RGB_888; +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN + if (visual == &compositor->premultiplied_argb_visual) + return COGL_PIXEL_FORMAT_BGRA_8888_PRE; + else if (visual == &compositor->argb_visual) + return COGL_PIXEL_FORMAT_BGRA_8888; + else if (visual == &compositor->rgb_visual) + return COGL_PIXEL_FORMAT_BGR_888; +#endif + else + g_return_val_if_reached (COGL_PIXEL_FORMAT_ANY); +} + +CoglTexture2D * +cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, + struct wl_buffer *buffer, + GError **error) +{ + CoglPixelFormat format = get_buffer_format (buffer); + + if (wl_buffer_is_shm (buffer)) + { + int stride = wl_shm_buffer_get_stride (buffer); + return cogl_texture_2d_new_from_data (ctx, + buffer->width, + buffer->height, + format, + COGL_PIXEL_FORMAT_ANY, + stride, + wl_shm_buffer_get_data (buffer), + error); + } + else + { + EGLImageKHR image; + + g_return_val_if_fail (_cogl_context_get_winsys (ctx) == + _cogl_winsys_egl_get_vtable (), + NULL); + image = _cogl_egl_create_image (ctx, + EGL_WAYLAND_BUFFER_WL, + buffer, + NULL); + return _cogl_egl_texture_2d_new_from_image (ctx, + buffer->width, + buffer->height, + format, + image, + error); + } +} +#endif /* COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT */ + void _cogl_texture_2d_externally_modified (CoglHandle handle) { diff --git a/cogl/cogl-texture-2d.h b/cogl/cogl-texture-2d.h index 1883cade3..be9a08c96 100644 --- a/cogl/cogl-texture-2d.h +++ b/cogl/cogl-texture-2d.h @@ -27,6 +27,10 @@ #ifndef __COGL_TEXURE_2D_H #define __COGL_TEXURE_2D_H +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +#include +#endif + #include G_BEGIN_DECLS @@ -179,6 +183,37 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx, CoglPixelFormat format, GError **error); +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT +/** + * cogl_wayland_texture_2d_new_from_buffer: + * @ctx: A #CoglContext + * @buffer: A Wayland buffer + * @error: A #GError for exceptions + * + * Uploads the given Wayland @buffer to a #CoglTexture2D. + * + * The results are undefined for passing an invalid @buffer + * pointer + * It is undefined if future updates to @buffer outside the + * control of Cogl will affect the allocated #CoglTexture2D. In some + * cases the contents of the buffer are copied (such as shm buffers), + * and in other cases the underlying storage is re-used directly (such + * as drm buffers) + * + * Returns: A newly allocated #CoglTexture2D, or if Cogl could not + * validate the @buffer in some way (perhaps because of + * an unsupported format) it will return %NULL and set + * @error. + * Since: 2.0 + */ +#define cogl_wayland_texture_2d_new_from_buffer \ + cogl_wayland_texture_2d_new_from_buffer_EXP +CoglTexture2D * +cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, + struct wl_buffer *buffer, + GError **error); +#endif /* COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT */ + G_END_DECLS #endif /* __COGL_TEXURE_2D_H */ diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h index 0a7bae009..796756319 100644 --- a/cogl/winsys/cogl-winsys-egl-feature-functions.h +++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h @@ -73,3 +73,14 @@ COGL_WINSYS_FEATURE_BEGIN (image_pixmap, "image_pixmap\0", COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_X11_PIXMAP) COGL_WINSYS_FEATURE_END () +COGL_WINSYS_FEATURE_BEGIN (bind_wayland_display, + "WL\0", + "bind_wayland_display\0", + COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER) +COGL_WINSYS_FEATURE_FUNCTION (EGLImageKHR, eglBindWaylandDisplay, + (EGLDisplay dpy, + struct wl_display *wayland_display)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglUnbindWaylandDisplay, + (EGLDisplay dpy, + struct wl_display *wayland_display)) +COGL_WINSYS_FEATURE_END () diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 857a55ad9..86a560b9f 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -1065,6 +1065,9 @@ _cogl_winsys_display_setup (CoglDisplay *display, GError **error) { CoglDisplayEGL *egl_display; +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + CoglRendererEGL *egl_renderer = display->renderer->winsys; +#endif g_return_val_if_fail (display->winsys == NULL, FALSE); @@ -1076,6 +1079,15 @@ _cogl_winsys_display_setup (CoglDisplay *display, goto error; #endif +#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT + if (display->wayland_compositor_display) + { + struct wl_display *wayland_display = display->wayland_compositor_display; + egl_renderer->pf_eglBindWaylandDisplay (egl_renderer->edpy, + wayland_display); + } +#endif + if (!create_context (display, error)) goto error; diff --git a/configure.ac b/configure.ac index 4a201d206..ad27450bd 100644 --- a/configure.ac +++ b/configure.ac @@ -614,6 +614,21 @@ AS_IF([test "x$enable_wayland_egl_platform" == "xyes"], AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_WAYLAND, [test "x$enable_wayland_egl_platform" = "xyes"]) +AC_ARG_ENABLE( + [wayland-egl-server], + [AC_HELP_STRING([--enable-wayland-egl-server=@<:@no/yes@:>@], [Enable server side wayland support @<:@default=no@:>@])], + [], + enable_wayland_egl_server=no +) +AS_IF([test "x$enable_wayland_egl_server" == "xyes"], + [ + NEED_EGL=yes + COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES wayland-server" + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_WAYLAND_EGL_SERVER, + [test "x$enable_wayland_egl_server" = "xyes"]) + dnl Android EGL platform AC_ARG_ENABLE( [android-egl-platform], @@ -875,6 +890,7 @@ echo " Driver: ${COGL_DRIVER} ${glesversion}" echo " GL Window System APIs:${GL_WINSYS_APIS}" if test "x$SUPPORT_EGL" = "xyes"; then echo " EGL Platforms:${EGL_PLATFORMS}" +echo " Wayland compositor support: ${enable_wayland_egl_server}" fi echo " Image backend: ${COGL_IMAGE_BACKEND}" echo " Cogl Pango: ${enable_cogl_pango}"