From: Damien Lespiau Date: Thu, 12 Aug 2010 13:25:17 +0000 (-0400) Subject: cex100: Add a Clutter EGL backend for CE3100/CE4100 SoCs X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e1e5db00327db6d37850aaad7bb8fb42ffe29e57;p=profile%2Fivi%2Fclutter.git cex100: Add a Clutter EGL backend for CE3100/CE4100 SoCs Intel CE3100 and CE4100 SoCs are designed for TVs. They have separate framebuffers that are blended together by a piece of hardware to make the final output. The library that allows you to initialize and configure those planes is called GDL. A EGL GDL winsys can then be use with those planes as NativeWindowType to select which plane to use. This patch adds a new ClutterBackendCex100 backend that can be selected at compile time with the new --with-flavour=cex100 option. --- diff --git a/clutter/cogl/cogl/Makefile.am b/clutter/cogl/cogl/Makefile.am index 696f3a4..9ba4e4f 100644 --- a/clutter/cogl/cogl/Makefile.am +++ b/clutter/cogl/cogl/Makefile.am @@ -206,6 +206,10 @@ if SUPPORT_EGL_PLATFORM_POWERVR_NULL libclutter_cogl_la_SOURCES += \ $(srcdir)/winsys/cogl-egl.c endif +if SUPPORT_EGL_PLATFORM_POWERVR_GDL +libclutter_cogl_la_SOURCES += \ + $(srcdir)/winsys/cogl-egl.c +endif if SUPPORT_EGL_PLATFORM_FRUITY libclutter_cogl_la_SOURCES += \ $(srcdir)/winsys/cogl-fruity.c diff --git a/clutter/egl/Makefile.am b/clutter/egl/Makefile.am index c3c7842..0559cc9 100644 --- a/clutter/egl/Makefile.am +++ b/clutter/egl/Makefile.am @@ -40,3 +40,6 @@ if USE_TSLIB libclutter_egl_la_SOURCES += clutter-event-tslib.c endif +if SUPPORT_CEX100 +libclutter_egl_la_SOURCES += clutter-backend-cex100.c clutter-backend-cex100.h +endif diff --git a/clutter/egl/clutter-backend-cex100.c b/clutter/egl/clutter-backend-cex100.c new file mode 100644 index 0000000..aee9b02 --- /dev/null +++ b/clutter/egl/clutter-backend-cex100.c @@ -0,0 +1,332 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Tao Zhao + * Damien Lespiau + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "clutter-debug.h" +#include "clutter-main.h" + +#include "clutter-backend-cex100.h" + +static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C; + +G_DEFINE_TYPE (ClutterBackendCex100, + clutter_backend_cex100, + CLUTTER_TYPE_BACKEND_EGL) + +static gboolean +gdl_plane_init (gdl_display_id_t dpy, + gdl_plane_id_t plane, + gdl_pixel_format_t pixfmt) +{ + gboolean ret = TRUE; + + gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB; + gdl_rectangle_t dstRect; + gdl_display_info_t display_info; + gdl_ret_t rc = GDL_SUCCESS; + + if (GDL_DISPLAY_ID_0 != dpy && GDL_DISPLAY_ID_1 != dpy) + { + g_warning ("Invalid display ID, must be GDL_DISPLAY_ID_0 or " + "GDL_DISPLAY_ID_1."); + return FALSE; + } + + /* Init GDL library */ + rc = gdl_init (NULL); + if (rc != GDL_SUCCESS) + { + g_warning ("GDL initialize failed. %s", gdl_get_error_string (rc)); + return FALSE; + } + + rc = gdl_get_display_info (dpy, &display_info); + if (rc != GDL_SUCCESS) + { + g_warning ("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 (plane); + if (rc == GDL_SUCCESS) + rc = gdl_plane_config_begin (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); + +#if 0 + /* + * Change the number of back buffers for the eglWindowSurface, Default + * value is 3, could be changed to 2, means one front buffer and one back + * buffer. + * + * TODO: Make a new API to tune that; + */ + if (rc == GDL_SUCCESS) + rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, 2); +#endif + + if (rc == GDL_SUCCESS) + rc = gdl_plane_config_end (GDL_FALSE); + else + gdl_plane_config_end (GDL_TRUE); + + if (rc != GDL_SUCCESS) + { + g_warning ("GDL configuration failed: %s.", gdl_get_error_string (rc)); + ret = FALSE; + } + + gdl_close (); + + return ret; +} + +/* + * ClutterBackendEGL implementation + */ + +static gboolean +clutter_backend_cex100_create_context (ClutterBackend *backend, + GError **error) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + EGLConfig configs[2]; + EGLint config_count; + EGLBoolean status; + + if (backend_egl->egl_context != EGL_NO_CONTEXT) + return TRUE; + + /* Start by initializing the GDL plane */ + if (!gdl_plane_init (GDL_DISPLAY_ID_0, gdl_plane, GDL_PF_ARGB_32)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Could not initialize the GDL plane"); + return FALSE; + } + + NativeWindowType window = (NativeWindowType) gdl_plane; + EGLint cfg_attribs[] = { + EGL_BUFFER_SIZE, EGL_DONT_CARE, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_ALPHA_SIZE, 8, + EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE, + EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE, +#ifdef HAVE_COGL_GLES2 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else /* HAVE_COGL_GLES2 */ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, +#endif /* HAVE_COGL_GLES2 */ + EGL_NONE + }; + + status = eglGetConfigs (backend_egl->edpy, + configs, + 2, + &config_count); + + if (status != EGL_TRUE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "No EGL configurations found"); + return FALSE; + } + + status = eglChooseConfig (backend_egl->edpy, + cfg_attribs, + configs, + G_N_ELEMENTS (configs), + &config_count); + + if (status != EGL_TRUE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to select a valid EGL configuration"); + return FALSE; + } + + CLUTTER_NOTE (BACKEND, "Got %i configs", config_count); + + if (status != EGL_TRUE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to Make Current Context for NULL"); + return FALSE; + } + + if (G_UNLIKELY (backend_egl->egl_surface != EGL_NO_SURFACE)) + { + eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface); + backend_egl->egl_surface = EGL_NO_SURFACE; + } + + if (G_UNLIKELY (backend_egl->egl_context != NULL)) + { + eglDestroyContext (backend_egl->edpy, backend_egl->egl_context); + backend_egl->egl_context = NULL; + } + + backend_egl->egl_surface = eglCreateWindowSurface (backend_egl->edpy, + configs[0], + window, + NULL); + + if (backend_egl->egl_surface == EGL_NO_SURFACE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to create EGL window surface"); + + return FALSE; + } + +#ifdef HAVE_COGL_GLES2 + { + static const EGLint attribs[3] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + backend_egl->egl_context = eglCreateContext (backend_egl->edpy, + configs[0], + EGL_NO_CONTEXT, + attribs); + } +#else + /* Seems some GLES implementations 1.x do not like attribs... */ + backend_egl->egl_context = eglCreateContext (backend_egl->edpy, + configs[0], + EGL_NO_CONTEXT, + NULL); +#endif + + if (backend_egl->egl_context == EGL_NO_CONTEXT) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to create a suitable EGL context"); + return FALSE; + } + + CLUTTER_NOTE (GL, "Created EGL Context"); + + CLUTTER_NOTE (BACKEND, "Setting context"); + + /* + * eglnative can have only one stage, so we store the EGL surface in the + * backend itself, instead of the StageWindow implementation, and we make it + * current immediately to make sure the Cogl and Clutter can query the EGL + * context for features. + */ + status = eglMakeCurrent (backend_egl->edpy, + backend_egl->egl_surface, + backend_egl->egl_surface, + backend_egl->egl_context); + + eglQuerySurface (backend_egl->edpy, + backend_egl->egl_surface, + EGL_WIDTH, + &backend_egl->surface_width); + + eglQuerySurface (backend_egl->edpy, + backend_egl->egl_surface, + EGL_HEIGHT, + &backend_egl->surface_height); + + CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i", + backend_egl->surface_width, + backend_egl->surface_height); + + /* + * For EGL backend, it needs to clear all the back buffers of the window + * surface before drawing anything, otherwise the image will be blinking + * heavily. The default eglWindowSurface has 3 gdl surfaces as the back + * buffer, that's why glClear should be called 3 times. + */ + glClearColor (0.0f, 0.0f, 0.0f, 0.0f); + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface); + + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface); + + glClear (GL_COLOR_BUFFER_BIT); + eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface); + + return TRUE; +} + +/* + * GObject implementation + */ + +static void +clutter_backend_cex100_class_init (ClutterBackendCex100Class *klass) +{ + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + backend_class->create_context = clutter_backend_cex100_create_context; +} + +static void +clutter_backend_cex100_init (ClutterBackendCex100 *self) +{ +} + +/* every backend must implement this function */ +GType +_clutter_backend_impl_get_type (void) +{ + return clutter_backend_cex100_get_type (); +} diff --git a/clutter/egl/clutter-backend-cex100.h b/clutter/egl/clutter-backend-cex100.h new file mode 100644 index 0000000..79e03d0 --- /dev/null +++ b/clutter/egl/clutter-backend-cex100.h @@ -0,0 +1,60 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Damien Lespiau + */ + +#ifndef __CLUTTER_BACKEND_CEX100_H__ +#define __CLUTTER_BACKEND_CEX100_H__ + +#include + +#include + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_CEX100 (clutter_backend_cex100_get_type()) +#define CLUTTER_BACKEND_CEX100(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100)) +#define CLUTTER_BACKEND_CEX100_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100Class)) +#define CLUTTER_IS_BACKEND_CEX100(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_CEX100)) +#define CLUTTER_IS_BACKEND_CEX100_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_CEX100)) +#define CLUTTER_BACKEND_CEX100_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100Class)) + +typedef struct _ClutterBackendCex100 ClutterBackendCex100; +typedef struct _ClutterBackendCex100Class ClutterBackendCex100Class; + +struct _ClutterBackendCex100 +{ + ClutterBackendEGL parent; +}; + +struct _ClutterBackendCex100Class +{ + ClutterBackendEGLClass parent_class; +}; + +GType clutter_backend_cex100_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_CEX100_H__ */ diff --git a/clutter/egl/clutter-backend-egl.c b/clutter/egl/clutter-backend-egl.c index d5e8ad5..dafa685 100644 --- a/clutter/egl/clutter-backend-egl.c +++ b/clutter/egl/clutter-backend-egl.c @@ -780,11 +780,13 @@ _clutter_backend_egl_init (ClutterBackendEGL *backend_egl) #endif } +#ifdef CLUTTER_EGL_BACKEND_GENERIC GType _clutter_backend_impl_get_type (void) { return _clutter_backend_egl_get_type (); } +#endif #ifdef COGL_HAS_XLIB_SUPPORT EGLDisplay diff --git a/configure.ac b/configure.ac index 6465596..5b241a5 100644 --- a/configure.ac +++ b/configure.ac @@ -138,7 +138,7 @@ experimental_backend=no experimental_image=no AC_ARG_WITH([flavour], - [AC_HELP_STRING([--with-flavour=@<:@glx/opengl-egl-xlib/eglx/eglnative/osx/win32/fruity@:>@], + [AC_HELP_STRING([--with-flavour=@<:@glx/opengl-egl-xlib/eglx/eglnative/osx/win32/fruity/cex100@:>@], [Select the Clutter window system backend])], [CLUTTER_FLAVOUR=$with_flavour]) @@ -194,6 +194,7 @@ AS_CASE([$CLUTTER_FLAVOUR], [ cogl_gl_headers="GL/gl.h" CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" + CLUTTER_EGL_BACKEND="generic" SUPPORT_X11=1 SUPPORT_XLIB=1 @@ -217,6 +218,7 @@ AS_CASE([$CLUTTER_FLAVOUR], [ # the GL header is defined in the COGL checks above CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" + CLUTTER_EGL_BACKEND="generic" SUPPORT_X11=1 SUPPORT_XLIB=1 @@ -235,6 +237,7 @@ AS_CASE([$CLUTTER_FLAVOUR], [ # the GL header is defined in the COGL checks above CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGLNATIVE" + CLUTTER_EGL_BACKEND="cex100" SUPPORT_EGL=1 SUPPORT_EGL_PLATFORM_POWERVR_NULL=1 @@ -253,6 +256,35 @@ AS_CASE([$CLUTTER_FLAVOUR], CLUTTER_SONAME_INFIX=eglnative ], + [cex100], + [ + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" + + SUPPORT_EGL=1 + SUPPORT_EGL_PLATFORM_POWERVR_GDL=1 + + COGL_DRIVER="gles" + + # The cex100 is a small specialization of the EGL backend + CLUTTER_WINSYS=egl + CLUTTER_SONAME_INFIX=cex100 + + found_gdl=no + AC_CHECK_HEADERS([libgdl.h], found_gdl=yes) + AS_IF([test x"$found_gdl" = "xno"], + AC_CHECK_HEADERS([CE4100/libgdl.h], + [ + FLAVOUR_CFLAGS="-I/usr/include/CE4100" + found_gdl=yes + ]) + ) + + AS_IF([test x"$found_gdl" = "xno"], + AC_MSG_ERROR([libgdl.h not found])) + + FLAVOUR_LIBS="$FLAVOUR_LIBS -lgdl" + ], + [fruity], [ experimental_backend="yes" @@ -343,6 +375,12 @@ AS_IF([test "x$SUPPORT_EGL" = "x1"], AC_DEFINE([COGL_HAS_EGL_SUPPORT], [1], [Cogl supports GLES using the EGL API]) ]) +AS_IF([test "x$CLUTTER_EGL_BACKEND" = "xgeneric"], + AC_DEFINE([CLUTTER_EGL_BACKEND_GENERIC], [1], [Use Generic EGL backend])) + +AS_IF([test "x$CLUTTER_EGL_BACKEND" = "xcex100"], + AC_DEFINE([CLUTTER_EGL_BACKEND_CEX100], [1], [Use CEX100 EGL backend])) + AS_IF([test "x$SUPPORT_EGL_POWERVR_X11" = "x1"], [ AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT], [1], @@ -355,6 +393,13 @@ AS_IF([test "x$SUPPORT_EGL_POWERVR_NULL" = "x1"], [Cogl supports OpenGLES using the EGL API with PowerVR NULL platform typedefs]) ]) +AS_IF([test "x$SUPPORT_EGL_POWERVR_GDL" = "x1"], + [ + AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT], [1], + [Cogl supports OpenGLES using the EGL API with PowerVR GDL platform typedefs]) + ]) + + # winsys conditionals for use in automake files... AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "x1"]) AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "x1"]) @@ -362,9 +407,11 @@ AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "x1"]) AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "x1"]) AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_X11, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_X11" = "x1"]) AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_NULL, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"]) +AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_GDL, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_GDL" = "x1"]) AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_FRUITY, [test "x$CLUTTER_WINSYS" = "xfruity"]) AM_CONDITIONAL(SUPPORT_OSX, [test "x$CLUTTER_WINSYS" = "xosx"]) AM_CONDITIONAL(SUPPORT_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"]) +AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_GDL" = "x1"]) dnl === COGL driver backend =====================================================