From f4365821148f1885ca2bbecedbf0270aa5af3edf Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Mon, 16 May 2011 16:43:30 +0100 Subject: [PATCH] android: Add support for an EGL/Android winsys The native window type of the EGL/Android winsys is ANativeWinow*. The Android NDK gives you a pointer to this ANativeWindow and you just need to configure that window using the EGLConfig you are choosing when creating the context. This means you have to know the ANativeWindow* window before creating the context. This is solved here by just having a global variable you can set with cogl_android_set_native_window() before creating the context. This is a bit ugly though, and it conceptually belongs to the OnScreen creation to know which ANativeWindow* to use. This would need a "lazy context creation" mechanism, waiting for the user to create the OnScreen to initialize the GL context. --- cogl/Makefile.am | 4 ++ cogl/cogl-context.h | 8 ++++ cogl/winsys/cogl-winsys-egl.c | 75 +++++++++++++++++++++++++++++++++-- configure.ac | 21 ++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 000bbf1ac..a0ccc391e 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -347,6 +347,10 @@ if SUPPORT_EGL_PLATFORM_WAYLAND cogl_sources_c += \ $(srcdir)/winsys/cogl-winsys-egl.c endif +if SUPPORT_EGL_PLATFORM_ANDROID +cogl_sources_c += \ + $(srcdir)/winsys/cogl-winsys-egl.c +endif if SUPPORT_STUB cogl_sources_c += \ $(srcdir)/winsys/cogl-winsys-stub.c diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h index bce47f1f2..7a6276d6b 100644 --- a/cogl/cogl-context.h +++ b/cogl/cogl-context.h @@ -33,6 +33,9 @@ #include #include +#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT +#include +#endif G_BEGIN_DECLS @@ -68,6 +71,11 @@ EGLDisplay cogl_context_egl_get_egl_display (CoglContext *context); #endif +#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT +void +cogl_android_set_native_window (ANativeWindow *window); +#endif + G_END_DECLS #endif /* __COGL_CONTEXT_H__ */ diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 268a13a27..49b1965a2 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -48,6 +48,10 @@ #include #endif +#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT +#include +#endif + #include #include #include @@ -111,7 +115,8 @@ typedef struct _CoglDisplayEGL struct wl_egl_window *wayland_egl_native_window; EGLSurface dummy_surface; #elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \ - defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) + defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \ + defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) EGLSurface egl_surface; int egl_surface_width; int egl_surface_height; @@ -206,6 +211,16 @@ initialize_function_table (CoglRenderer *renderer) #include "cogl-winsys-egl-feature-functions.h" } +#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT +static ANativeWindow *android_native_window; + +void +cogl_android_set_native_window (ANativeWindow *window) +{ + android_native_window = window; +} +#endif + #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT static CoglOnscreen * find_onscreen_for_xid (CoglContext *context, guint32 xid) @@ -749,6 +764,58 @@ try_create_context (CoglDisplay *display, goto fail; } +#elif defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) + { + EGLint format; + + if (android_native_window == NULL) + { + error_message = "No ANativeWindow window specified with " + "cogl_android_set_native_window()"; + goto fail; + } + + /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is + * guaranteed to be accepted by ANativeWindow_setBuffersGeometry (). + * As soon as we picked a EGLConfig, we can safely reconfigure the + * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ + eglGetConfigAttrib (edpy, config, EGL_NATIVE_VISUAL_ID, &format); + + ANativeWindow_setBuffersGeometry (android_native_window, + 0, + 0, + format); + + egl_display->egl_surface = + eglCreateWindowSurface (edpy, + config, + (NativeWindowType) android_native_window, + NULL); + if (egl_display->egl_surface == EGL_NO_SURFACE) + { + error_message = "Unable to create EGL window surface"; + goto fail; + } + + if (!eglMakeCurrent (egl_renderer->edpy, + egl_display->egl_surface, + egl_display->egl_surface, + egl_display->egl_context)) + { + error_message = "Unable to eglMakeCurrent with egl surface"; + goto fail; + } + + eglQuerySurface (egl_renderer->edpy, + egl_display->egl_surface, + EGL_WIDTH, + &egl_display->egl_surface_width); + + eglQuerySurface (egl_renderer->edpy, + egl_display->egl_surface, + EGL_HEIGHT, + &egl_display->egl_surface_height); + } #elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) egl_display->egl_surface = @@ -1219,7 +1286,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, wl_surface_map_toplevel (egl_onscreen->wayland_surface); -#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) +#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \ + defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) if (egl_display->have_onscreen) { g_set_error (error, COGL_WINSYS_ERROR, @@ -1328,7 +1396,8 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen) egl_display->dummy_surface, egl_display->egl_context); egl_context->current_surface = egl_display->dummy_surface; -#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) +#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \ + defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) return; #else #error "Unknown EGL platform" diff --git a/configure.ac b/configure.ac index 7583070b5..0ce53280f 100644 --- a/configure.ac +++ b/configure.ac @@ -610,6 +610,27 @@ AS_IF([test "x$enable_wayland_egl_platform" == "xyes"], AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_WAYLAND, [test "x$enable_wayland_egl_platform" = "xyes"]) +dnl Android EGL platform +AC_ARG_ENABLE( + [android-egl-platform], + [AC_HELP_STRING([--enable-android-egl-platform=@<:@no/yes@:>@], [Enable support for the Android egl platform @<:@default=no@:>@])], + [], + enable_android_egl_platform=no +) +AS_IF([test "x$enable_android_egl_platform" == "xyes"], + [ + EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1)) + NEED_EGL=yes + EGL_PLATFORMS="$EGL_PLATFORMS android" + + AC_CHECK_HEADER([android/native_window.h], + [], + [AC_MSG_ERROR([Unable to locate android/native_window.h])]) + + COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT" + ]) +AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_ANDROID, + [test "x$enable_android_egl_platform" = "xyes"]) dnl This should go last, since it's the default fallback and we need dnl to check the value of $EGL_PLATFORM_COUNT here.