diff --git a/cogl/winsys/cogl-winsys-egl-gdl.c b/cogl/winsys/cogl-winsys-egl-gdl.c index 407503573..1f7a2c38c 100644 --- a/cogl/winsys/cogl-winsys-egl-gdl.c +++ b/cogl/winsys/cogl-winsys-egl-gdl.c @@ -31,6 +31,322 @@ #include "cogl-winsys-egl-gdl-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-onscreen-template-private.h" +#include "cogl-swap-chain-private.h" + +static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; + +typedef struct _CoglRendererGDL +{ + gboolean gdl_initialized; +} CoglRendererGDL; + +typedef struct _CoglDisplayGDL +{ + int egl_surface_width; + int egl_surface_height; + gboolean have_onscreen; +} CoglDisplayGDL; + +static void +_cogl_winsys_renderer_disconnect (CoglRenderer *renderer) +{ + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglRendererGDL *gdl_renderer = egl_renderer->platform; + + if (gdl_renderer->gdl_initialized) + gdl_close (); + + eglTerminate (egl_renderer->edpy); + + g_slice_free (CoglRendererEGL, egl_renderer); +} + +static gboolean +_cogl_winsys_renderer_connect (CoglRenderer *renderer, + GError **error) +{ + CoglRendererEGL *egl_renderer; + CoglRendererGDL *gdl_renderer; + gdl_ret_t rc = GDL_SUCCESS; + gdl_display_info_t gdl_display_info; + + renderer->winsys = g_slice_new0 (CoglRendererEGL); + egl_renderer = renderer->winsys; + + gdl_renderer = g_slice_new0 (CoglRendererGDL); + egl_renderer->platform = gdl_renderer; + + 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; + + /* Check we can talk to the GDL library */ + rc = gdl_init (NULL); + if (rc != GDL_SUCCESS) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "GDL initialize failed. %s", + gdl_get_error_string (rc)); + goto error; + } + + rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &gdl_display_info); + if (rc != GDL_SUCCESS) + { + g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_INIT, + "GDL failed to get display information: %s", + gdl_get_error_string (rc)); + gdl_close (); + goto error; + } + + gdl_close (); + + 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; + CoglDisplayGDL *gdl_display = egl_display->platform; + const char *error_message; + + egl_display->egl_surface = + eglCreateWindowSurface (egl_renderer->edpy, + egl_display->egl_config, + (NativeWindowType) display->gdl_plane, + 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, + &gdl_display->egl_surface_width); + + eglQuerySurface (egl_renderer->edpy, + egl_display->egl_surface, + EGL_HEIGHT, + &gdl_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 +gdl_plane_init (CoglDisplay *display, GError **error) +{ + gboolean ret = TRUE; + gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB; + gdl_pixel_format_t pixfmt = GDL_PF_ARGB_32; + gdl_rectangle_t dstRect; + gdl_display_info_t display_info; + gdl_ret_t rc = GDL_SUCCESS; + + if (!display->gdl_plane) + { + g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, + "No GDL plane specified with " + "cogl_gdl_display_set_plane"); + return FALSE; + } + + rc = gdl_init (NULL); + if (rc != GDL_SUCCESS) + { + g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, + "GDL initialize failed. %s", gdl_get_error_string (rc)); + return FALSE; + } + + rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &display_info); + if (rc != GDL_SUCCESS) + { + g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, + "GDL failed to get display infomation: %s", + gdl_get_error_string (rc)); + gdl_close (); + return FALSE; + } + + dstRect.origin.x = 0; + dstRect.origin.y = 0; + dstRect.width = display_info.tvmode.width; + dstRect.height = display_info.tvmode.height; + + /* Configure the plane attribute. */ + rc = gdl_plane_reset (display->gdl_plane); + if (rc == GDL_SUCCESS) + rc = gdl_plane_config_begin (display->gdl_plane); + + if (rc == GDL_SUCCESS) + rc = gdl_plane_set_attr (GDL_PLANE_SRC_COLOR_SPACE, &colorSpace); + + if (rc == GDL_SUCCESS) + rc = gdl_plane_set_attr (GDL_PLANE_PIXEL_FORMAT, &pixfmt); + + if (rc == GDL_SUCCESS) + rc = gdl_plane_set_attr (GDL_PLANE_DST_RECT, &dstRect); + + /* Default to triple buffering if the swap_chain doesn't have an explicit + * length */ + if (rc == GDL_SUCCESS) + { + if (display->onscreen_template->config.swap_chain && + display->onscreen_template->config.swap_chain->length != -1) + rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, + display->onscreen_template-> + config.swap_chain->length); + else + rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, 3); + } + + if (rc == GDL_SUCCESS) + rc = gdl_plane_config_end (GDL_FALSE); + else + gdl_plane_config_end (GDL_TRUE); + + if (rc != GDL_SUCCESS) + { + g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, + "GDL configuration failed: %s.", gdl_get_error_string (rc)); + ret = FALSE; + } + + gdl_close (); + + return ret; +} + +static gboolean +_cogl_winsys_egl_display_setup (CoglDisplay *display, + GError **error) +{ + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayGDL *gdl_display; + + gdl_display = g_slice_new0 (CoglDisplayGDL); + egl_display->platform = gdl_display; + + if (!gdl_plane_init (display, error)) + return FALSE; + + return TRUE; +} + +static void +_cogl_winsys_egl_display_destroy (CoglDisplay *display) +{ + CoglDisplayEGL *egl_display = display->winsys; + + g_slice_free (CoglDisplayGDL, egl_display->platform); +} + +static void +_cogl_winsys_egl_cleanup_context (CoglDisplay *display) +{ + CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; + CoglDisplayEGL *egl_display = display->winsys; + + if (egl_display->egl_surface != EGL_NO_SURFACE) + { + eglDestroySurface (egl_renderer->edpy, egl_display->egl_surface); + egl_display->egl_surface = EGL_NO_SURFACE; + } +} + +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; + CoglDisplayGDL *gdl_display = egl_display->platform; + CoglOnscreenEGL *egl_onscreen = onscreen->winsys; + + if (gdl_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, + gdl_display->egl_surface_width, + gdl_display->egl_surface_height); + gdl_display->have_onscreen = TRUE; + + return TRUE; +} + +static int +_cogl_winsys_egl_add_config_attributes (CoglDisplay *display, + CoglFramebufferConfig *config, + EGLint *attributes) +{ + int i = 0; + + /* XXX: Why does the GDL platform choose these by default? */ + attributes[i++] = EGL_BIND_TO_TEXTURE_RGBA; + attributes[i++] = EGL_TRUE; + attributes[i++] = EGL_BIND_TO_TEXTURE_RGB; + attributes[i++] = EGL_TRUE; + + return i; +} + +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, + .cleanup_context = _cogl_winsys_egl_cleanup_context, + .onscreen_init = _cogl_winsys_egl_onscreen_init, + .add_config_attributes = _cogl_winsys_egl_add_config_attributes + }; const CoglWinsysVtable * _cogl_winsys_egl_gdl_get_vtable (void) @@ -48,6 +364,9 @@ _cogl_winsys_egl_gdl_get_vtable (void) vtable.id = COGL_WINSYS_ID_EGL_GDL; vtable.name = "EGL_GDL"; + 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 721931cae..8c385fc7f 100644 --- a/cogl/winsys/cogl-winsys-egl-private.h +++ b/cogl/winsys/cogl-winsys-egl-private.h @@ -28,6 +28,7 @@ #include "cogl-winsys-private.h" #include "cogl-context.h" #include "cogl-context-private.h" +#include "cogl-framebuffer-private.h" typedef struct _CoglWinsysEGLVtable { @@ -61,6 +62,11 @@ typedef struct _CoglWinsysEGLVtable GError **error); void (* onscreen_deinit) (CoglOnscreen *onscreen); + + int + (* add_config_attributes) (CoglDisplay *display, + CoglFramebufferConfig *config, + EGLint *attributes); } CoglWinsysEGLVtable; typedef enum _CoglEGLWinsysFeature @@ -82,10 +88,6 @@ typedef struct _CoglRendererEGL EGLint egl_version_major; EGLint egl_version_minor; -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - gboolean gdl_initialized; -#endif - /* Data specific to the EGL platform */ void *platform; /* vtable for platform specific parts */ @@ -110,8 +112,7 @@ typedef struct _CoglDisplayEGL { EGLContext egl_context; EGLSurface dummy_surface; -#if defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \ - defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) +#if defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) int egl_surface_width; int egl_surface_height; gboolean have_onscreen; diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 8d2009305..a4cbca5e4 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -121,12 +121,6 @@ _cogl_winsys_renderer_disconnect (CoglRenderer *renderer) { CoglRendererEGL *egl_renderer = renderer->winsys; -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_GDL && - egl_renderer->gdl_initialized) - gdl_close (); -#endif - eglTerminate (egl_renderer->edpy); g_slice_free (CoglRendererEGL, egl_renderer); @@ -183,10 +177,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, GError **error) { CoglRendererEGL *egl_renderer; -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - gdl_ret_t rc = GDL_SUCCESS; - gdl_display_info_t gdl_display_info; -#endif renderer->winsys = g_slice_new0 (CoglRendererEGL); @@ -198,7 +188,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, g_warn_if_reached (); goto error; - case COGL_WINSYS_ID_EGL_GDL: case COGL_WINSYS_ID_EGL_ANDROID: egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); break; @@ -207,36 +196,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, if (!_cogl_winsys_egl_renderer_connect_common (renderer, error)) goto error; -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_GDL) - { - /* Check we can talk to the GDL library */ - - rc = gdl_init (NULL); - if (rc != GDL_SUCCESS) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_INIT, - "GDL initialize failed. %s", - gdl_get_error_string (rc)); - goto error; - } - - rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &gdl_display_info); - if (rc != GDL_SUCCESS) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_INIT, - "GDL failed to get display information: %s", - gdl_get_error_string (rc)); - gdl_close (); - goto error; - } - - gdl_close (); - } -#endif - return TRUE; error: @@ -251,8 +210,16 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display, EGLint *attributes) { CoglRenderer *renderer = display->renderer; + CoglRendererEGL *egl_renderer = renderer->winsys; int i = 0; + /* Let the platform add attributes first */ + if (egl_renderer->platform_vtable && + egl_renderer->platform_vtable->add_config_attributes) + i = egl_renderer->platform_vtable->add_config_attributes (display, + config, + attributes); + attributes[i++] = EGL_STENCIL_SIZE; attributes[i++] = needs_stencil_override ? 2 : 0; @@ -269,17 +236,6 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display, attributes[i++] = EGL_DEPTH_SIZE; attributes[i++] = 1; - /* XXX: Why does the GDL platform choose these by default? */ -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_GDL) - { - attributes[i++] = EGL_BIND_TO_TEXTURE_RGBA; - attributes[i++] = EGL_TRUE; - attributes[i++] = EGL_BIND_TO_TEXTURE_RGB; - attributes[i++] = EGL_TRUE; - } -#endif - attributes[i++] = EGL_BUFFER_SIZE; attributes[i++] = EGL_DONT_CARE; @@ -435,41 +391,6 @@ try_create_context (CoglDisplay *display, } break; #endif - -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - case COGL_WINSYS_ID_EGL_GDL: - egl_display->egl_surface = - eglCreateWindowSurface (edpy, - config, - (NativeWindowType) display->gdl_plane, - 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 } return TRUE; @@ -499,22 +420,6 @@ cleanup_context (CoglDisplay *display) if (egl_renderer->platform_vtable && egl_renderer->platform_vtable->cleanup_context) egl_renderer->platform_vtable->cleanup_context (display); - - switch (renderer->winsys_vtable->id) - { - default: - break; - -#if defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) - case COGL_WINSYS_ID_EGL_GDL: - if (egl_display->egl_surface != EGL_NO_SURFACE) - { - eglDestroySurface (egl_renderer->edpy, egl_display->egl_surface); - egl_display->egl_surface = EGL_NO_SURFACE; - } - break; -#endif - } } static gboolean @@ -560,92 +465,6 @@ _cogl_winsys_display_destroy (CoglDisplay *display) display->winsys = NULL; } -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT -static gboolean -gdl_plane_init (CoglDisplay *display, GError **error) -{ - gboolean ret = TRUE; - gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB; - gdl_pixel_format_t pixfmt = GDL_PF_ARGB_32; - gdl_rectangle_t dstRect; - gdl_display_info_t display_info; - gdl_ret_t rc = GDL_SUCCESS; - - if (!display->gdl_plane) - { - g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, - "No GDL plane specified with " - "cogl_gdl_display_set_plane"); - return FALSE; - } - - rc = gdl_init (NULL); - if (rc != GDL_SUCCESS) - { - g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, - "GDL initialize failed. %s", gdl_get_error_string (rc)); - return FALSE; - } - - rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &display_info); - if (rc != GDL_SUCCESS) - { - g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, - "GDL failed to get display infomation: %s", - gdl_get_error_string (rc)); - gdl_close (); - return FALSE; - } - - dstRect.origin.x = 0; - dstRect.origin.y = 0; - dstRect.width = display_info.tvmode.width; - dstRect.height = display_info.tvmode.height; - - /* Configure the plane attribute. */ - rc = gdl_plane_reset (display->gdl_plane); - if (rc == GDL_SUCCESS) - rc = gdl_plane_config_begin (display->gdl_plane); - - if (rc == GDL_SUCCESS) - rc = gdl_plane_set_attr (GDL_PLANE_SRC_COLOR_SPACE, &colorSpace); - - if (rc == GDL_SUCCESS) - rc = gdl_plane_set_attr (GDL_PLANE_PIXEL_FORMAT, &pixfmt); - - if (rc == GDL_SUCCESS) - rc = gdl_plane_set_attr (GDL_PLANE_DST_RECT, &dstRect); - - /* Default to triple buffering if the swap_chain doesn't have an explicit - * length */ - if (rc == GDL_SUCCESS) - { - if (display->onscreen_template->swap_chain && - display->onscreen_template->swap_chain->length != -1) - rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, - display->onscreen_template->swap_chain->length); - else - rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, 3); - } - - if (rc == GDL_SUCCESS) - rc = gdl_plane_config_end (GDL_FALSE); - else - gdl_plane_config_end (GDL_TRUE); - - if (rc != GDL_SUCCESS) - { - g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, - "GDL configuration failed: %s.", gdl_get_error_string (rc)); - ret = FALSE; - } - - gdl_close (); - - return TRUE; -} -#endif - static gboolean _cogl_winsys_display_setup (CoglDisplay *display, GError **error) @@ -659,12 +478,6 @@ _cogl_winsys_display_setup (CoglDisplay *display, egl_display = g_slice_new0 (CoglDisplayEGL); display->winsys = egl_display; -#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT - if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_GDL && - !gdl_plane_init (display, error)) - goto error; -#endif - #ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT if (display->wayland_compositor_display) { @@ -806,10 +619,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, } break; -#if defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) || \ - defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) +#if defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) case COGL_WINSYS_ID_EGL_ANDROID: - case COGL_WINSYS_ID_EGL_GDL: if (egl_display->have_onscreen) {