diff --git a/cogl/winsys/cogl-winsys-egl-android.c b/cogl/winsys/cogl-winsys-egl-android.c index e4bdea53a..2efa6b267 100644 --- a/cogl/winsys/cogl-winsys-egl-android.c +++ b/cogl/winsys/cogl-winsys-egl-android.c @@ -29,8 +29,197 @@ #include "config.h" #endif +#include + #include "cogl-winsys-egl-android-private.h" #include "cogl-winsys-egl-private.h" +#include "cogl-renderer-private.h" +#include "cogl-framebuffer-private.h" +#include "cogl-onscreen-private.h" +#include "cogl-private.h" + +static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; + +typedef struct _CoglDisplayAndroid +{ + int egl_surface_width; + int egl_surface_height; + gboolean have_onscreen; +} CoglDisplayAndroid; + +static ANativeWindow *android_native_window; + +void +cogl_android_set_native_window (ANativeWindow *window) +{ + _cogl_init (); + + android_native_window = window; +} + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + CoglRendererEGL *egl_renderer = renderer->winsys; + + eglTerminate (egl_renderer->edpy); + + g_slice_free (CoglRendererEGL, egl_renderer); +} + +static gboolean +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + GError **error) +{ + CoglRendererEGL *egl_renderer; + + renderer->winsys = g_slice_new0 (CoglRendererEGL); + egl_renderer = renderer->winsys; + + egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; + + egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); + + if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) + goto error; + + return TRUE; + +error: + _cogl_winsys_renderer_disconnect (renderer); + return FALSE; +} + +static gboolean +_cogl_winsys_egl_context_created (CoglDisplay *display, + GError **error) +{ + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayAndroid *android_display = egl_display->platform; + const char *error_message; + 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 (egl_renderer->edpy, + egl_display->egl_config, + EGL_NATIVE_VISUAL_ID, &format); + + ANativeWindow_setBuffersGeometry (android_native_window, + 0, + 0, + format); + + egl_display->egl_surface = + eglCreateWindowSurface (egl_renderer->edpy, + egl_display->egl_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, + &android_display->egl_surface_width); + + eglQuerySurface (egl_renderer->edpy, + egl_display->egl_surface, + EGL_HEIGHT, + &android_display->egl_surface_height); + + return TRUE; + + fail: + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "%s", error_message); + return FALSE; +} + +static gboolean +_cogl_winsys_egl_display_setup (CoglDisplay *display, + GError **error) +{ + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayAndroid *android_display; + + android_display = g_slice_new0 (CoglDisplayAndroid); + egl_display->platform = android_display; + + return TRUE; +} + +static void +_cogl_winsys_egl_display_destroy (CoglDisplay *display) +{ + CoglDisplayEGL *egl_display = display->winsys; + + g_slice_free (CoglDisplayAndroid, egl_display->platform); +} + +static gboolean +_cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen, + EGLConfig egl_config, + GError **error) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayAndroid *android_display = egl_display->platform; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + if (android_display->have_onscreen) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_ONSCREEN, + "EGL platform only supports a single onscreen window"); + return FALSE; + } + + egl_onscreen->egl_surface = egl_display->egl_surface; + + _cogl_framebuffer_winsys_update_size (framebuffer, + android_display->egl_surface_width, + android_display->egl_surface_height); + + android_display->have_onscreen = TRUE; + + return TRUE; +} + +static const CoglWinsysEGLVtable +_cogl_winsys_egl_vtable = + { + .display_setup = _cogl_winsys_egl_display_setup, + .display_destroy = _cogl_winsys_egl_display_destroy, + .context_created = _cogl_winsys_egl_context_created, + .onscreen_init = _cogl_winsys_egl_onscreen_init, + }; const CoglWinsysVtable * _cogl_winsys_egl_android_get_vtable (void) @@ -48,6 +237,9 @@ _cogl_winsys_egl_android_get_vtable (void) vtable.id = COGL_WINSYS_ID_EGL_ANDROID; vtable.name = "EGL_ANDROID"; + vtable.renderer_connect = _cogl_winsys_renderer_connect; + vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect; + vtable_inited = TRUE; } diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h index 8c385fc7f..6658278a0 100644 --- a/cogl/winsys/cogl-winsys-egl-private.h +++ b/cogl/winsys/cogl-winsys-egl-private.h @@ -112,11 +112,6 @@ typedef struct _CoglDisplayEGL { EGLContext egl_context; EGLSurface dummy_surface; -#if defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) - int egl_surface_width; - int egl_surface_height; - gboolean have_onscreen; -#endif EGLSurface egl_surface; EGLConfig egl_config; diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index a4cbca5e4..ce5d5da39 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -43,10 +43,6 @@ #include "cogl-private.h" -#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT -#include -#endif - #include #include #include @@ -104,26 +100,11 @@ _cogl_winsys_renderer_get_proc_address (CoglRenderer *renderer, return ptr; } -#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT -static ANativeWindow *android_native_window; - -void -cogl_android_set_native_window (ANativeWindow *window) -{ - _cogl_init (); - - android_native_window = window; -} -#endif - static void _cogl_winsys_renderer_disconnect (CoglRenderer *renderer) { - CoglRendererEGL *egl_renderer = renderer->winsys; - - eglTerminate (egl_renderer->edpy); - - g_slice_free (CoglRendererEGL, egl_renderer); + /* This function must be overridden by a platform winsys */ + g_assert_not_reached (); } /* Updates all the function pointers */ @@ -176,31 +157,8 @@ static gboolean _cogl_winsys_renderer_connect (CoglRenderer *renderer, GError **error) { - CoglRendererEGL *egl_renderer; - - renderer->winsys = g_slice_new0 (CoglRendererEGL); - - egl_renderer = renderer->winsys; - - switch (renderer->winsys_vtable->id) - { - default: - g_warn_if_reached (); - goto error; - - case COGL_WINSYS_ID_EGL_ANDROID: - egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); - break; - } - - if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) - goto error; - - return TRUE; - -error: - _cogl_winsys_renderer_disconnect (renderer); - return FALSE; + /* This function must be overridden by a platform winsys */ + g_assert_not_reached (); } static void @@ -214,8 +172,7 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display, int i = 0; /* Let the platform add attributes first */ - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->add_config_attributes) + if (egl_renderer->platform_vtable->add_config_attributes) i = egl_renderer->platform_vtable->add_config_attributes (display, config, attributes); @@ -293,8 +250,7 @@ try_create_context (CoglDisplay *display, attribs[0] = EGL_NONE; /* Divert to the platform implementation if one is defined */ - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->try_create_context) + if (egl_renderer->platform_vtable->try_create_context) return egl_renderer->platform_vtable-> try_create_context (display, attribs, error); @@ -327,71 +283,9 @@ try_create_context (CoglDisplay *display, goto fail; } - switch (renderer->winsys_vtable->id) - { - default: - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->context_created && - !egl_renderer->platform_vtable->context_created (display, error)) - return FALSE; - break; - -#ifdef COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT - case COGL_WINSYS_ID_EGL_ANDROID: - { - 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); - } - break; -#endif - } + if (egl_renderer->platform_vtable->context_created && + !egl_renderer->platform_vtable->context_created (display, error)) + return FALSE; return TRUE; @@ -417,8 +311,7 @@ cleanup_context (CoglDisplay *display) egl_display->egl_context = EGL_NO_CONTEXT; } - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->cleanup_context) + if (egl_renderer->platform_vtable->cleanup_context) egl_renderer->platform_vtable->cleanup_context (display); } @@ -457,8 +350,7 @@ _cogl_winsys_display_destroy (CoglDisplay *display) cleanup_context (display); - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->display_destroy) + if (egl_renderer->platform_vtable->display_destroy) egl_renderer->platform_vtable->display_destroy (display); g_slice_free (CoglDisplayEGL, display->winsys); @@ -489,8 +381,7 @@ _cogl_winsys_display_setup (CoglDisplay *display, } #endif - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->display_setup && + if (egl_renderer->platform_vtable->display_setup && !egl_renderer->platform_vtable->display_setup (display, error)) goto error; @@ -532,8 +423,7 @@ _cogl_winsys_context_init (CoglContext *context, GError **error) COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE); } - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->context_init && + if (egl_renderer->platform_vtable->context_init && !egl_renderer->platform_vtable->context_init (context, error)) return FALSE; @@ -546,8 +436,7 @@ _cogl_winsys_context_deinit (CoglContext *context) CoglRenderer *renderer = context->display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->context_deinit) + if (egl_renderer->platform_vtable->context_deinit) egl_renderer->platform_vtable->context_deinit (context); g_free (context->winsys); @@ -563,7 +452,6 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, CoglDisplayEGL *egl_display = display->winsys; CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; - CoglOnscreenEGL *egl_onscreen; EGLint attributes[MAX_EGL_CONFIG_ATTRIBS]; EGLConfig egl_config; EGLint config_count = 0; @@ -603,41 +491,14 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, } onscreen->winsys = g_slice_new0 (CoglOnscreenEGL); - egl_onscreen = onscreen->winsys; - switch (renderer->winsys_vtable->id) + if (egl_renderer->platform_vtable->onscreen_init && + !egl_renderer->platform_vtable->onscreen_init (onscreen, + egl_config, + error)) { - default: - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->onscreen_init && - !egl_renderer->platform_vtable->onscreen_init (onscreen, - egl_config, - error)) - { - g_slice_free (CoglOnscreenEGL, onscreen->winsys); - return FALSE; - } - break; - -#if defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) - case COGL_WINSYS_ID_EGL_ANDROID: - - if (egl_display->have_onscreen) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_CREATE_ONSCREEN, - "EGL platform only supports a single onscreen window"); - return FALSE; - } - - egl_onscreen->egl_surface = egl_display->egl_surface; - - _cogl_framebuffer_winsys_update_size (framebuffer, - egl_display->egl_surface_width, - egl_display->egl_surface_height); - egl_display->have_onscreen = TRUE; - break; -#endif + g_slice_free (CoglOnscreenEGL, onscreen->winsys); + return FALSE; } return TRUE; @@ -663,8 +524,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen) egl_onscreen->egl_surface = EGL_NO_SURFACE; } - if (egl_renderer->platform_vtable && - egl_renderer->platform_vtable->onscreen_deinit) + if (egl_renderer->platform_vtable->onscreen_deinit) egl_renderer->platform_vtable->onscreen_deinit (onscreen); g_slice_free (CoglOnscreenEGL, onscreen->winsys);