$(srcdir)/evdev/clutter-input-device-evdev.h \
$(NULL)
-egl_cex_c_priv = $(srcdir)/egl/clutter-backend-cex100.c
-egl_cex_h_priv = $(srcdir)/egl/clutter-backend-cex100.h
egl_cex_h = $(srcdir)/egl/clutter-cex100.h
if SUPPORT_EGL
endif # SUPPORT_EVDEV
if SUPPORT_CEX100
-egl_source_c_priv += $(egl_cex_c_priv)
-egl_source_h_priv += $(egl_cex_h_priv)
egl_source_h += $(egl_cex_h)
endif # SUPPORT_CEX100
endif
if SUPPORT_EGL_PLATFORM_POWERVR_X11
cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c \
- $(srcdir)/winsys/cogl-winsys-stub.c
+ $(srcdir)/winsys/cogl-winsys-egl.c
endif
if SUPPORT_EGL_PLATFORM_POWERVR_NULL
cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c \
- $(srcdir)/winsys/cogl-winsys-stub.c
+ $(srcdir)/winsys/cogl-winsys-egl.c
endif
if SUPPORT_EGL_PLATFORM_POWERVR_GDL
cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c \
- $(srcdir)/winsys/cogl-winsys-stub.c
+ $(srcdir)/winsys/cogl-winsys-egl.c
endif
if SUPPORT_WIN32
cogl_sources_c += \
cogl_object_unref (_context);
_context = context;
}
+
+#ifdef COGL_HAS_EGL_SUPPORT
+EGLDisplay
+cogl_context_egl_get_egl_display (CoglContext *context)
+{
+ return _cogl_winsys_context_egl_get_egl_display (context);
+}
+#endif
+
#include <cogl/cogl-display.h>
+#ifdef COGL_HAS_EGL_SUPPORT
+#ifdef COGL_HAS_GLES1
+#include <GLES/gl.h>
+#include <GLES/egl.h>
+#else
+#include <EGL/egl.h>
+#define NativeDisplayType EGLNativeDisplayType
+#define NativeWindowType EGLNativeWindowType
+#endif
+#endif
+
G_BEGIN_DECLS
/**
void
cogl_set_default_context (CoglContext *context);
+#ifdef COGL_HAS_EGL_SUPPORT
+#define cogl_context_egl_get_egl_display cogl_context_egl_get_egl_display_EXP
+EGLDisplay
+cogl_context_egl_get_egl_display (CoglContext *context);
+#endif
+
G_END_DECLS
#endif /* __COGL_CONTEXT_H__ */
--- /dev/null
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * 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
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+/* This can be included multiple times with different definitions for
+ * the COGL_WINSYS_FEATURE_* functions.
+ */
+
+/* Macro prototypes:
+ * COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
+ * implied_public_feature_flags,
+ * implied_private_feature_flags,
+ * implied_winsys_feature)
+ * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
+ * (arguments))
+ * ...
+ * COGL_WINSYS_FEATURE_END ()
+ *
+ * Note: You can list multiple namespace and extension names if the
+ * corresponding _FEATURE_FUNCTIONS have the same semantics accross
+ * the different extension variants.
+ *
+ * XXX: NB: Don't add a trailing semicolon when using these macros
+ */
+
+COGL_WINSYS_FEATURE_BEGIN (swap_region,
+ "NOK\0",
+ "swap_region\0",
+ 0,
+ 0,
+ COGL_WINSYS_FEATURE_SWAP_REGION)
+COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersRegion,
+ (EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint numRects,
+ const EGLint *rects))
+COGL_WINSYS_FEATURE_END ()
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
- * Copyright (C) 2007,2008,2009 Intel Corporation.
+ * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* 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 <http://www.gnu.org/licenses/>.
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
*
*
+ * Authors:
+ * Robert Bragg <robert@linux.intel.com>
*/
#ifdef HAVE_CONFIG_H
#include "cogl.h"
-#ifdef HAVE_STANDALONE_EGL
+#include "cogl-winsys-private.h"
+#include "cogl-feature-private.h"
+#include "cogl-context-private.h"
+#include "cogl-framebuffer.h"
+#include "cogl-swap-chain-private.h"
+#include "cogl-renderer-private.h"
+#include "cogl-onscreen-template-private.h"
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+#include "cogl-renderer-xlib-private.h"
+#include "cogl-display-xlib-private.h"
+#endif
+#include "cogl-private.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib/gi18n-lib.h>
+
+#ifdef COGL_HAS_GLES1
+
+#include <GLES/gl.h>
+#include <GLES/egl.h>
+
+#else
+
#include <EGL/egl.h>
-#include <EGL/eglext.h>
#define NativeDisplayType EGLNativeDisplayType
#define NativeWindowType EGLNativeWindowType
+
+#endif
+
+
+#include <EGL/egl.h>
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+#include <X11/Xlib.h>
+#endif
+
+typedef struct _CoglRendererEGL
+{
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglRendererXlib _parent;
+#endif
+
+ EGLDisplay edpy;
+
+ EGLint egl_version_major;
+ EGLint egl_version_minor;
+
+ /* Function pointers for GLX specific extensions */
+#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
+
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+ ret (APIENTRY * pf_ ## name) args;
+
+#define COGL_WINSYS_FEATURE_END()
+
+#include "cogl-winsys-egl-feature-functions.h"
+
+#undef COGL_WINSYS_FEATURE_BEGIN
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#undef COGL_WINSYS_FEATURE_END
+} CoglRendererEGL;
+
+typedef struct _CoglDisplayEGL
+{
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglDisplayXlib _parent;
+#endif
+
+ EGLContext egl_context;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ EGLSurface dummy_surface;
+#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
+ EGLSurface egl_surface;
+ int egl_surface_width;
+ int egl_surface_height;
+ gboolean have_onscreen;
#else
-#include <GLES/egl.h>
-#include <GLES/eglext.h>
+#error "Unknown EGL platform"
#endif
+ EGLConfig egl_config;
+ gboolean found_egl_config;
+} CoglDisplayEGL;
+
+typedef struct _CoglContextEGL
+{
+ EGLSurface current_surface;
+} CoglContextEGL;
+
+typedef struct _CoglOnscreenXlib
+{
+ Window xwin;
+ gboolean is_foreign_xwin;
+} CoglOnscreenXlib;
+
+typedef struct _CoglOnscreenEGL
+{
+ CoglOnscreenXlib _parent;
+ EGLSurface egl_surface;
+} CoglOnscreenEGL;
+
+/* Define a set of arrays containing the functions required from GL
+ for each winsys feature */
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
+ feature_flags, feature_flags_private, \
+ winsys_feature) \
+ static const CoglFeatureFunction \
+ cogl_egl_feature_ ## name ## _funcs[] = {
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+ { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererEGL, pf_ ## name) },
+#define COGL_WINSYS_FEATURE_END() \
+ { NULL, 0 }, \
+ };
+#include "cogl-winsys-egl-feature-functions.h"
+
+/* Define an array of features */
+#undef COGL_WINSYS_FEATURE_BEGIN
+#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
+ feature_flags, feature_flags_private, \
+ winsys_feature) \
+ { 255, 255, namespaces, extension_names, \
+ feature_flags, feature_flags_private, \
+ winsys_feature, \
+ cogl_egl_feature_ ## name ## _funcs },
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
+#undef COGL_WINSYS_FEATURE_END
+#define COGL_WINSYS_FEATURE_END()
+
+static const CoglFeatureData winsys_feature_data[] =
+ {
+#include "cogl-winsys-egl-feature-functions.h"
+ };
+
CoglFuncPtr
_cogl_winsys_get_proc_address (const char *name)
{
return (CoglFuncPtr) eglGetProcAddress (name);
}
+#undef COGL_WINSYS_FEATURE_BEGIN
+#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
+#undef COGL_WINSYS_FEATURE_FUNCTION
+#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
+ egl_renderer->pf_ ## name = NULL;
+#undef COGL_WINSYS_FEATURE_END
+#define COGL_WINSYS_FEATURE_END()
+
+static void
+initialize_function_table (CoglRenderer *renderer)
+{
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+
+#include "cogl-winsys-egl-feature-functions.h"
+}
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+static CoglOnscreen *
+find_onscreen_for_xid (CoglContext *context, guint32 xid)
+{
+ GList *l;
+
+ for (l = context->framebuffers; l; l = l->next)
+ {
+ CoglFramebuffer *framebuffer = l->data;
+ CoglOnscreenXlib *xlib_onscreen;
+
+ if (!framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
+ continue;
+
+ xlib_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
+ if (xlib_onscreen->xwin == (Window)xid)
+ return COGL_ONSCREEN (framebuffer);
+ }
+
+ return NULL;
+}
+
+static CoglFilterReturn
+event_filter_cb (void *event, void *data)
+{
+ XEvent *xevent = event;
+ CoglContext *context = data;
+
+ if (xevent->type == ConfigureNotify)
+ {
+ CoglOnscreen *onscreen =
+ find_onscreen_for_xid (context, xevent->xconfigure.window);
+
+ if (onscreen)
+ {
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+
+ /* XXX: consider adding an abstraction for this... */
+ framebuffer->width = xevent->xconfigure.width;
+ framebuffer->height = xevent->xconfigure.height;
+ }
+ }
+
+ return COGL_FILTER_CONTINUE;
+}
+#endif /* COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT */
+
+gboolean
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+ GError **error)
+{
+ CoglRendererEGL *egl_renderer;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglRendererXlib *xlib_renderer;
+#endif
+ EGLBoolean status;
+
+ renderer->winsys = g_slice_new0 (CoglRendererEGL);
+
+ egl_renderer = renderer->winsys;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ xlib_renderer = renderer->winsys;
+
+ if (!_cogl_renderer_xlib_connect (renderer, error))
+ goto error;
+
+ egl_renderer->edpy =
+ eglGetDisplay ((NativeDisplayType) xlib_renderer->xdpy);
+
+ status = eglInitialize (egl_renderer->edpy,
+ &egl_renderer->egl_version_major,
+ &egl_renderer->egl_version_minor);
+#else
+ egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+
+ status = eglInitialize (egl_renderer->edpy,
+ &egl_renderer->egl_version_major,
+ &egl_renderer->egl_version_minor);
+
+ if (status != EGL_TRUE)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Failed to initialize EGL");
+ goto error;
+ }
+#endif
+
+ return TRUE;
+
+error:
+ _cogl_winsys_renderer_disconnect (renderer);
+ return FALSE;
+}
+
+void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ _cogl_renderer_xlib_disconnect (renderer);
+#endif
+
+ eglTerminate (egl_renderer->edpy);
+
+ g_slice_free (CoglRendererEGL, egl_renderer);
+}
+
+void
+update_winsys_features (CoglContext *context)
+{
+ CoglDisplayEGL *egl_display = context->display->winsys;
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+ const char *egl_extensions;
+ int i;
+
+ g_return_if_fail (egl_display->egl_context);
+
+ _cogl_gl_update_features (context);
+
+ memset (context->winsys_features, 0, sizeof (context->winsys_features));
+
+ egl_extensions = eglQueryString (egl_renderer->edpy, EGL_EXTENSIONS);
+
+ COGL_NOTE (WINSYS, " EGL Extensions: %s", egl_extensions);
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
+ COGL_FLAGS_SET (context->winsys_features,
+ COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
+ TRUE);
+#endif
+
+ initialize_function_table (context->display->renderer);
+
+ for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
+ if (_cogl_feature_check ("EGL", winsys_feature_data + i, 0, 0,
+ egl_extensions,
+ egl_renderer))
+ {
+ context->feature_flags |= winsys_feature_data[i].feature_flags;
+ if (winsys_feature_data[i].winsys_feature)
+ COGL_FLAGS_SET (context->winsys_features,
+ winsys_feature_data[i].winsys_feature,
+ TRUE);
+ }
+
+ /* FIXME: the winsys_feature_data can currently only have one
+ * winsys feature per extension... */
+ if (egl_renderer->pf_eglSwapBuffersRegion)
+ {
+ COGL_FLAGS_SET (context->winsys_features,
+ COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
+ COGL_FLAGS_SET (context->winsys_features,
+ COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
+ }
+}
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+static XVisualInfo *
+get_visual_info (CoglDisplay *display, EGLConfig egl_config)
+{
+ CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
+ XVisualInfo visinfo_template;
+ int template_mask = 0;
+ XVisualInfo *visinfo = NULL;
+ int visinfos_count;
+ EGLint visualid, red_size, green_size, blue_size, alpha_size;
+
+ eglGetConfigAttrib (egl_renderer->edpy, egl_config,
+ EGL_NATIVE_VISUAL_ID, &visualid);
+
+ if (visualid != 0)
+ {
+ visinfo_template.visualid = visualid;
+ template_mask |= VisualIDMask;
+ }
+ else
+ {
+ /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
+ * attribute, so attempt to find the closest match. */
+
+ eglGetConfigAttrib (egl_renderer->edpy, egl_config,
+ EGL_RED_SIZE, &red_size);
+ eglGetConfigAttrib (egl_renderer->edpy, egl_config,
+ EGL_GREEN_SIZE, &green_size);
+ eglGetConfigAttrib (egl_renderer->edpy, egl_config,
+ EGL_BLUE_SIZE, &blue_size);
+ eglGetConfigAttrib (egl_renderer->edpy, egl_config,
+ EGL_ALPHA_SIZE, &alpha_size);
+
+ visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
+ template_mask |= VisualDepthMask;
+
+ visinfo_template.screen = DefaultScreen (xlib_renderer->xdpy);
+ template_mask |= VisualScreenMask;
+ }
+
+ visinfo = XGetVisualInfo (xlib_renderer->xdpy,
+ template_mask,
+ &visinfo_template,
+ &visinfos_count);
+
+ return visinfo;
+}
+#endif
+
+static gboolean
+try_create_context (CoglDisplay *display,
+ int retry_cookie,
+ gboolean *try_fallback,
+ GError **error)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglDisplayXlib *xlib_display = display->winsys;
+ CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+#endif
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
+ EGLDisplay edpy;
+ EGLConfig config;
+ EGLint config_count = 0;
+ EGLBoolean status;
+ EGLint cfg_attribs[] = {
+ /* NB: This must be the first attribute, since we may
+ * try and fallback to no stencil buffer */
+ EGL_STENCIL_SIZE, 2,
+
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+
+ EGL_DEPTH_SIZE, 1,
+
+ EGL_BUFFER_SIZE, EGL_DONT_CARE,
+
+#if defined (HAVE_COGL_GL)
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+#elif defined (HAVE_COGL_GLES2)
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#else
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+
+ EGL_NONE
+ };
+#if defined (HAVE_COGL_GLES2)
+ EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+#else
+ EGLint *attribs = NULL;
+#endif
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ XVisualInfo *xvisinfo;
+ XSetWindowAttributes attrs;
+#endif
+ const char *error_message;
+
+ edpy = egl_renderer->edpy;
+
+#ifdef HAVE_COGL_GL
+ eglBindAPI (EGL_OPENGL_API);
+#endif
+
+ /* Some GLES hardware can't support a stencil buffer: */
+ if (retry_cookie == 1)
+ {
+ g_warning ("Trying with stencil buffer disabled...");
+ cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
+ }
+ /* XXX: at this point we only have one fallback */
+
+ status = eglChooseConfig (edpy,
+ cfg_attribs,
+ &config, 1,
+ &config_count);
+ if (status != EGL_TRUE || config_count == 0)
+ {
+ error_message = "Unable to find a usable EGL configuration";
+ goto fail;
+ }
+
+ egl_display->egl_config = config;
+
+ egl_display->egl_context = eglCreateContext (edpy,
+ config,
+ EGL_NO_CONTEXT,
+ attribs);
+ if (egl_display->egl_context == EGL_NO_CONTEXT)
+ {
+ error_message = "Unable to create a suitable EGL context";
+ goto fail;
+ }
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+
+ xvisinfo = get_visual_info (display, config);
+ if (xvisinfo == NULL)
+ {
+ error_message = "Unable to find suitable X visual";
+ goto fail;
+ }
+
+ attrs.override_redirect = True;
+ attrs.colormap = XCreateColormap (xlib_renderer->xdpy,
+ DefaultRootWindow (xlib_renderer->xdpy),
+ xvisinfo->visual,
+ AllocNone);
+ attrs.border_pixel = 0;
+
+ xlib_display->dummy_xwin =
+ XCreateWindow (xlib_renderer->xdpy,
+ DefaultRootWindow (xlib_renderer->xdpy),
+ -100, -100, 1, 1,
+ 0,
+ xvisinfo->depth,
+ CopyFromParent,
+ xvisinfo->visual,
+ CWOverrideRedirect |
+ CWColormap |
+ CWBorderPixel,
+ &attrs);
+
+ XFree (xvisinfo);
+
+ egl_display->dummy_surface =
+ eglCreateWindowSurface (edpy,
+ egl_display->egl_config,
+ (NativeWindowType) xlib_display->dummy_xwin,
+ NULL);
+
+ if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Unable to create an EGL surface");
+ goto fail;
+ }
+
+ if (!eglMakeCurrent (edpy,
+ egl_display->dummy_surface,
+ egl_display->dummy_surface,
+ egl_display->egl_context))
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Unable to eglMakeCurrent with dummy surface");
+ goto fail;
+ }
+
+#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
+
+ egl_display->egl_surface =
+ eglCreateWindowSurface (edpy,
+ config,
+ (NativeWindowType) NULL,
+ NULL);
+ if (egl_display->egl_surface == EGL_NO_SURFACE)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "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))
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "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);
+
+#else
+#error "Unknown EGL platform"
+#endif
+
+ return TRUE;
+
+fail:
+
+ /* Currently we only have one fallback path... */
+ if (retry_cookie == 0)
+ {
+ *try_fallback = TRUE;
+ return FALSE;
+ }
+ else
+ {
+ *try_fallback = FALSE;
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "%s", error_message);
+ return FALSE;
+ }
+}
+
+static void
+cleanup_context (CoglDisplay *display)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglDisplayXlib *xlib_display = display->winsys;
+ CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+#endif
+
+ if (egl_display->egl_context != EGL_NO_CONTEXT)
+ {
+ eglMakeCurrent (egl_renderer->edpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroyContext (egl_renderer->edpy, egl_display->egl_context);
+ egl_display->egl_context = EGL_NO_CONTEXT;
+ }
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ if (egl_display->dummy_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface);
+ egl_display->dummy_surface = EGL_NO_SURFACE;
+ }
+
+ if (xlib_display->dummy_xwin)
+ {
+ XDestroyWindow (xlib_renderer->xdpy, xlib_display->dummy_xwin);
+ xlib_display->dummy_xwin = None;
+ }
+#endif
+}
+
+static gboolean
+create_context (CoglDisplay *display, GError **error)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+ gboolean support_transparent_windows;
+ int retry_cookie = 0;
+ gboolean status;
+ gboolean try_fallback;
+ GError *try_error = NULL;
+
+ g_return_val_if_fail (egl_display->egl_context == NULL, TRUE);
+
+ if (display->onscreen_template &&
+ display->onscreen_template->swap_chain &&
+ display->onscreen_template->swap_chain->has_alpha)
+ support_transparent_windows = TRUE;
+ else
+ support_transparent_windows = FALSE;
+
+ retry_cookie = 0;
+ while (!(status = try_create_context (display,
+ retry_cookie,
+ &try_fallback,
+ &try_error)) &&
+ try_fallback)
+ {
+ g_error_free (try_error);
+ cleanup_context (display);
+ try_error = NULL;
+ retry_cookie++;
+ }
+ if (!status)
+ g_propagate_error (error, try_error);
+
+ return status;
+}
+
+gboolean
+_cogl_winsys_display_setup (CoglDisplay *display,
+ GError **error)
+{
+ CoglDisplayEGL *egl_display;
+
+ g_return_val_if_fail (display->winsys == NULL, FALSE);
+
+ egl_display = g_slice_new0 (CoglDisplayEGL);
+ display->winsys = egl_display;
+
+ if (!create_context (display, error))
+ goto error;
+
+ egl_display->found_egl_config = TRUE;
+
+ return TRUE;
+
+error:
+ _cogl_winsys_display_destroy (display);
+ return FALSE;
+}
+
+void
+_cogl_winsys_display_destroy (CoglDisplay *display)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+
+ g_return_if_fail (egl_display != NULL);
+
+ cleanup_context (display);
+
+ g_slice_free (CoglDisplayEGL, display->winsys);
+ display->winsys = NULL;
+}
+
+gboolean
+_cogl_winsys_context_init (CoglContext *context, GError **error)
+{
+ context->winsys = g_new0 (CoglContextEGL, 1);
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ cogl_renderer_add_native_filter (context->display->renderer,
+ event_filter_cb,
+ context);
+#endif
+ update_winsys_features (context);
+
+ return TRUE;
+}
+
+void
+_cogl_winsys_context_deinit (CoglContext *context)
+{
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ cogl_renderer_remove_native_filter (context->display->renderer,
+ event_filter_cb,
+ context);
+#endif
+ g_free (context->winsys);
+}
+
+gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+ GError **error)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayEGL *egl_display = display->winsys;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
+ CoglRendererXlib *xlib_renderer = display->renderer->winsys;
+ CoglOnscreenXlib *xlib_onscreen;
+ Window xwin;
+#endif
+ CoglOnscreenEGL *egl_onscreen;
+
+ g_return_val_if_fail (egl_display->egl_context, FALSE);
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+
+ /* FIXME: We need to explicitly Select for ConfigureNotify events.
+ * For foreign windows we need to be careful not to mess up any
+ * existing event mask.
+ * We need to document that for windows we create then toolkits
+ * must be careful not to clear event mask bits that we select.
+ */
+
+ /* XXX: Note we ignore the user's original width/height when
+ * given a foreign X window. */
+ if (onscreen->foreign_xid)
+ {
+ Status status;
+ CoglXlibTrapState state;
+ XWindowAttributes attr;
+ int xerror;
+
+ xwin = onscreen->foreign_xid;
+
+ _cogl_renderer_xlib_trap_errors (display->renderer, &state);
+
+ status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr);
+ xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
+ if (status == 0 || xerror)
+ {
+ char message[1000];
+ XGetErrorText (xlib_renderer->xdpy, xerror,
+ message, sizeof (message));
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to query geometry of foreign xid 0x%08lX: %s",
+ xwin, message);
+ return FALSE;
+ }
+
+ _cogl_framebuffer_winsys_update_size (framebuffer,
+ attr.width, attr.height);
+ }
+ else
+ {
+ int width;
+ int height;
+ CoglXlibTrapState state;
+ XVisualInfo *xvisinfo;
+ XSetWindowAttributes xattr;
+ unsigned long mask;
+ int xerror;
+
+ width = cogl_framebuffer_get_width (framebuffer);
+ height = cogl_framebuffer_get_height (framebuffer);
+
+ _cogl_renderer_xlib_trap_errors (display->renderer, &state);
+
+ xvisinfo = get_visual_info (display, egl_display->egl_config);
+ if (xvisinfo == NULL)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Unable to retrieve the X11 visual of context's "
+ "fbconfig");
+ return FALSE;
+ }
+
+ /* window attributes */
+ xattr.background_pixel = WhitePixel (xlib_renderer->xdpy,
+ DefaultScreen (xlib_renderer->xdpy));
+ xattr.border_pixel = 0;
+ /* XXX: is this an X resource that we are leaking‽... */
+ xattr.colormap = XCreateColormap (xlib_renderer->xdpy,
+ DefaultRootWindow (xlib_renderer->xdpy),
+ xvisinfo->visual,
+ AllocNone);
+ mask = CWBorderPixel | CWColormap;
+
+ xwin = XCreateWindow (xlib_renderer->xdpy,
+ DefaultRootWindow (xlib_renderer->xdpy),
+ 0, 0,
+ width, height,
+ 0,
+ xvisinfo->depth,
+ InputOutput,
+ xvisinfo->visual,
+ mask, &xattr);
+
+ XFree (xvisinfo);
+
+ XMapWindow (xlib_renderer->xdpy, xwin);
+
+ XSync (xlib_renderer->xdpy, False);
+ xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
+ if (xerror)
+ {
+ char message[1000];
+ XGetErrorText (xlib_renderer->xdpy, xerror,
+ message, sizeof (message));
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "X error while creating Window for CoglOnscreen: %s",
+ message);
+ return FALSE;
+ }
+ }
+#endif
+
+ onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
+ egl_onscreen = onscreen->winsys;
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ xlib_onscreen = onscreen->winsys;
+
+ xlib_onscreen->xwin = xwin;
+ xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE;
+
+ egl_onscreen->egl_surface =
+ eglCreateWindowSurface (egl_renderer->edpy,
+ egl_display->egl_config,
+ (NativeWindowType) xlib_onscreen->xwin,
+ NULL);
+#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
+ 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;
+#else
+#error "Unknown EGL platform"
+#endif
+
+ return TRUE;
+}
+
+void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
+ CoglXlibTrapState old_state;
+ CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
+ CoglDisplayEGL *egl_display = context->display->winsys;
+#endif
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
+ {
+ if (eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface)
+ == EGL_FALSE)
+ g_warning ("Failed to destroy EGL surface");
+ egl_onscreen->egl_surface = EGL_NO_SURFACE;
+ }
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT
+ egl_display->have_onscreen = FALSE;
+#endif
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ _cogl_xlib_trap_errors (&old_state);
+
+ if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None)
+ {
+ XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
+ xlib_onscreen->xwin = None;
+ }
+ else
+ xlib_onscreen->xwin = None;
+
+ XSync (xlib_renderer->xdpy, False);
+
+ if (_cogl_xlib_untrap_errors (&old_state) != Success)
+ g_warning ("X Error while destroying X window");
+#endif
+}
+
+void
+_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglContextEGL *egl_context = context->winsys;
+ CoglDisplayEGL *egl_display = context->display->winsys;
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ if (egl_context->current_surface == egl_onscreen->egl_surface)
+ return;
+
+ if (G_UNLIKELY (!onscreen))
+ {
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ eglMakeCurrent (egl_renderer->edpy,
+ egl_display->dummy_surface,
+ 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)
+ return;
+#else
+#error "Unknown EGL platform"
+#endif
+ }
+ else
+ {
+ eglMakeCurrent (egl_renderer->edpy,
+ egl_onscreen->egl_surface,
+ egl_onscreen->egl_surface,
+ egl_display->egl_context);
+ egl_context->current_surface = egl_onscreen->egl_surface;
+ }
+
+ if (onscreen->swap_throttled)
+ eglSwapInterval (egl_renderer->edpy, 1);
+ else
+ eglSwapInterval (egl_renderer->edpy, 0);
+}
+
+void
+_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
+ int *rectangles,
+ int n_rectangles)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
+ egl_onscreen->egl_surface,
+ n_rectangles,
+ rectangles) == EGL_FALSE)
+ g_warning ("Error reported by eglSwapBuffersRegion");
+}
+
+guint32
+_cogl_winsys_get_vsync_counter (void)
+{
+ /* Unsupported feature */
+ return 0;
+}
+
+void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
+}
+
+guint32
+_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
+{
+ CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
+ return xlib_onscreen->xwin;
+}
+
+unsigned int
+_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
+ CoglSwapBuffersNotify callback,
+ void *user_data)
+{
+ /* Unsupported feature */
+ return 0;
+}
+
+void
+_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
+ unsigned int id)
+{
+ /* Unsupported feature */
+}
+
+void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglContextEGL *egl_context = context->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+
+ if (egl_context->current_surface != egl_onscreen->egl_surface)
+ return;
+
+ egl_context->current_surface = EGL_NO_SURFACE;
+ _cogl_winsys_onscreen_bind (onscreen);
+}
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+/* XXX: This is a particularly hacky _cogl_winsys interface... */
+XVisualInfo *
+_cogl_winsys_xlib_get_visual_info (void)
+{
+ CoglDisplayEGL *egl_display;
+
+ _COGL_GET_CONTEXT (ctx, NULL);
+
+ g_return_val_if_fail (ctx->display->winsys, FALSE);
+
+ egl_display = ctx->display->winsys;
+
+ if (!egl_display->found_egl_config)
+ return NULL;
+
+ return get_visual_info (ctx->display, egl_display->egl_config);
+}
+#endif
+
+EGLDisplay
+_cogl_winsys_context_egl_get_egl_display (CoglContext *context)
+{
+ CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
+
+ return egl_renderer->edpy;
+}
void
_cogl_winsys_context_deinit (CoglContext *context);
+#ifdef COGL_HAS_EGL_SUPPORT
+EGLDisplay
+_cogl_winsys_context_egl_get_egl_display (CoglContext *context);
+#endif
+
gboolean
_cogl_winsys_has_feature (CoglWinsysFeature feature);
+++ /dev/null
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Tao Zhao <tao.zhao@intel.com>
- * Damien Lespiau <damien.lespiau@intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "clutter-debug.h"
-#include "clutter-main.h"
-
-#include "clutter-backend-cex100.h"
-#include "clutter-cex100.h"
-
-static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
-static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
-
-G_DEFINE_TYPE (ClutterBackendCex100,
- clutter_backend_cex100,
- CLUTTER_TYPE_BACKEND_EGL)
-
-#ifdef CLUTTER_ENABLE_DEBUG
-static const gchar *
-gdl_get_plane_name (gdl_plane_id_t plane)
-{
- switch (plane)
- {
- case GDL_PLANE_ID_UPP_A:
- return "UPP_A";
- case GDL_PLANE_ID_UPP_B:
- return "UPP_B";
- case GDL_PLANE_ID_UPP_C:
- return "UPP_C";
- case GDL_PLANE_ID_UPP_D:
- return "UPP_D";
- case GDL_PLANE_ID_UPP_E:
- return "UPP_E";
- default:
- g_assert_not_reached ();
- }
-
- return NULL; /* never reached */
-}
-#endif
-
-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 (rc == GDL_SUCCESS)
- rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, gdl_n_buffers);
-
- 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;
- NativeWindowType window;
- 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
- };
-
- if (backend_egl->egl_context != EGL_NO_CONTEXT)
- return TRUE;
-
- CLUTTER_NOTE (BACKEND, "Using the %s plane", gdl_get_plane_name (gdl_plane));
-
- /* 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;
- }
-
- window = (NativeWindowType) gdl_plane;
-
- 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 ();
-}
-
-void
-clutter_cex100_set_plane (gdl_plane_id_t plane)
-{
- g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
-
- gdl_plane = plane;
-}
-
-void
-clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
-{
- g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
- mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
-
- gdl_n_buffers = mode;
-}
+++ /dev/null
-/*
- * 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 <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Damien Lespiau <damien.lespiau@intel.com>
- */
-
-#ifndef __CLUTTER_BACKEND_CEX100_H__
-#define __CLUTTER_BACKEND_CEX100_H__
-
-#include <libgdl.h>
-
-#include <glib-object.h>
-
-#include <clutter/egl/clutter-backend-egl.h>
-
-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__ */
#include "clutter-private.h"
#include "clutter-main.h"
#include "clutter-stage-private.h"
+/* FIXME: We should have CLUTTER_ define for this... */
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
+#include "clutter-cex100.h"
+#endif
static ClutterBackendEGL *backend_singleton = NULL;
-static const gchar *clutter_fb_device = NULL;
+static gchar *clutter_vblank = NULL;
-static gchar *clutter_vblank_name = NULL;
+/* FIXME: We should have CLUTTER_ define for this... */
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
+static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
+static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
+#endif
#ifdef COGL_HAS_X11_SUPPORT
G_DEFINE_TYPE (ClutterBackendEGL, _clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
g_object_run_dispose (G_OBJECT (backend_singleton));
}
+G_CONST_RETURN gchar*
+_clutter_backend_egl_get_vblank (void)
+{
+ if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
+ return "none";
+ else
+ return clutter_vblank;
+}
+
static gboolean
clutter_backend_egl_pre_parse (ClutterBackend *backend,
GError **error)
{
const gchar *env_string;
#ifdef COGL_HAS_X11_SUPPORT
- ClutterBackendClass *backend_x11_class =
+ ClutterBackendClass *parent_class =
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
- if (!backend_x11_class->pre_parse (backend, error))
+ if (!parent_class->pre_parse (backend, error))
return FALSE;
#endif
env_string = g_getenv ("CLUTTER_VBLANK");
if (env_string)
{
- clutter_vblank_name = g_strdup (env_string);
+ clutter_vblank = g_strdup (env_string);
env_string = NULL;
}
- env_string = g_getenv ("CLUTTER_FB_DEVICE");
- if (env_string != NULL && env_string[0] != '\0')
- clutter_fb_device = g_strdup (env_string);
-
return TRUE;
}
clutter_backend_egl_post_parse (ClutterBackend *backend,
GError **error)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
#ifdef COGL_HAS_X11_SUPPORT
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
- ClutterBackendClass *backend_x11_class =
+ ClutterBackendClass *parent_class =
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
-#endif
- EGLBoolean status;
-#ifdef COGL_HAS_X11_SUPPORT
- if (!backend_x11_class->post_parse (backend, error))
+ if (!parent_class->post_parse (backend, error))
return FALSE;
-#ifndef COGL_HAS_XLIB_SUPPORT
-#error "Clutter's EGL on X11 support currently only works with xlib Displays"
-#endif
- backend_egl->edpy =
- eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
-
- status = eglInitialize (backend_egl->edpy,
- &backend_egl->egl_version_major,
- &backend_egl->egl_version_minor);
-#else
- backend_egl->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
-
- status = eglInitialize (backend_egl->edpy,
- &backend_egl->egl_version_major,
- &backend_egl->egl_version_minor);
-#endif
-
- g_atexit (clutter_backend_at_exit);
-
- if (status != EGL_TRUE)
- {
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "Unable to Initialize EGL");
- return FALSE;
- }
-
- CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
- backend_egl->egl_version_major,
- backend_egl->egl_version_minor);
-
return TRUE;
-}
-
-void
-_clutter_backend_egl_blit_sub_buffer (ClutterBackendEGL *backend_egl,
- EGLSurface drawable,
- int x, int y, int width, int height)
-{
- if (backend_egl->swap_buffers_region)
- {
- EGLint rect[4] = {
- x, y, width, height
- };
- backend_egl->swap_buffers_region (backend_egl->edpy,
- drawable,
- 1,
- rect);
- }
-#if 0 /* XXX need GL_ARB_draw_buffers */
- else if (backend_egl->blit_framebuffer)
- {
- glDrawBuffer (GL_FRONT);
- backend_egl->blit_framebuffer (x, y, x + width, y + height,
- x, y, x + width, y + height,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- glDrawBuffer (GL_BACK);
- glFlush();
- }
-#endif
-}
-
-static gboolean
-clutter_backend_egl_create_context (ClutterBackend *backend,
- GError **error)
-{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
-#ifdef COGL_HAS_X11_SUPPORT
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
-#endif
- EGLConfig config;
- EGLint config_count = 0;
- EGLBoolean status;
- EGLint cfg_attribs[] = {
- /* NB: This must be the first attribute, since we may
- * try and fallback to no stencil buffer */
- EGL_STENCIL_SIZE, 2,
-
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, EGL_DONT_CARE,
-
- EGL_DEPTH_SIZE, 1,
-
- EGL_BUFFER_SIZE, EGL_DONT_CARE,
-
-#if defined (HAVE_COGL_GL)
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
-#elif defined (HAVE_COGL_GLES2)
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#else
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
-#endif
-
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-
- EGL_NONE
- };
- EGLDisplay edpy;
- gint retry_cookie = 0;
- const char *error_message = NULL;
-#ifdef COGL_HAS_XLIB_SUPPORT
- XVisualInfo *xvisinfo;
- XSetWindowAttributes attrs;
-#endif
-
- if (backend_egl->egl_context != EGL_NO_CONTEXT)
- return TRUE;
-
- edpy = clutter_egl_get_egl_display ();
-
-/* XXX: we should get rid of this goto yukkyness, there is a fail:
- * goto at the end and this retry: goto at the top, but we should just
- * have a try_create_context() function and call it in a loop that
- * tries a different fallback each iteration */
-retry:
- /* Here we can change the attributes depending on the fallback count... */
-
- /* Some GLES hardware can't support a stencil buffer: */
- if (retry_cookie == 1)
- {
- g_warning ("Trying with stencil buffer disabled...");
- cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
- }
-
- /* XXX: at this point we only have one fallback */
-
- status = eglChooseConfig (edpy,
- cfg_attribs,
- &config, 1,
- &config_count);
- if (status != EGL_TRUE || config_count == 0)
- {
- error_message = "Unable to select a valid EGL configuration";
- goto fail;
- }
-
-#ifdef HAVE_COGL_GL
- eglBindAPI (EGL_OPENGL_API);
-#endif
-
- if (backend_egl->egl_context == EGL_NO_CONTEXT)
- {
-#ifdef HAVE_COGL_GLES2
- static const EGLint attribs[] =
- { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-
- backend_egl->egl_context = eglCreateContext (edpy,
- config,
- EGL_NO_CONTEXT,
- attribs);
-
-#else
- backend_egl->egl_context = eglCreateContext (edpy,
- config,
- EGL_NO_CONTEXT,
- NULL);
-
#endif
- if (backend_egl->egl_context == EGL_NO_CONTEXT)
- {
- error_message = "Unable to create a suitable EGL context";
- goto fail;
- }
-
-#ifdef COGL_HAS_XLIB_SUPPORT
- backend_egl->egl_config = config;
-#endif
- CLUTTER_NOTE (GL, "Created EGL Context");
- }
-
-#ifdef COGL_HAS_XLIB_SUPPORT
- /* COGL assumes that there is always a GL context selected; in order
- * to make sure that an EGL context exists and is made current, we use
- * a dummy, offscreen override-redirect window to which we can always
- * fall back if no stage is available */
-
- xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
- if (xvisinfo == NULL)
- {
- g_critical ("Unable to find suitable GL visual.");
- return FALSE;
- }
-
- attrs.override_redirect = True;
- attrs.colormap = XCreateColormap (backend_x11->xdpy,
- backend_x11->xwin_root,
- xvisinfo->visual,
- AllocNone);
- attrs.border_pixel = 0;
-
- backend_egl->dummy_xwin = XCreateWindow (backend_x11->xdpy,
- backend_x11->xwin_root,
- -100, -100, 1, 1,
- 0,
- xvisinfo->depth,
- CopyFromParent,
- xvisinfo->visual,
- CWOverrideRedirect |
- CWColormap |
- CWBorderPixel,
- &attrs);
-
- XFree (xvisinfo);
-
- backend_egl->dummy_surface =
- eglCreateWindowSurface (edpy,
- backend_egl->egl_config,
- (NativeWindowType) backend_egl->dummy_xwin,
- NULL);
-
- if (backend_egl->dummy_surface == EGL_NO_SURFACE)
- {
- g_critical ("Unable to create an EGL surface");
- return FALSE;
- }
-
- eglMakeCurrent (edpy,
- backend_egl->dummy_surface,
- backend_egl->dummy_surface,
- backend_egl->egl_context);
-
-#else /* COGL_HAS_XLIB_SUPPORT */
-
- if (clutter_fb_device != NULL)
- {
- int fd = open (clutter_fb_device, O_RDWR);
-
- if (fd < 0)
- {
- int errno_save = errno;
-
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "Unable to open the framebuffer device '%s': %s",
- clutter_fb_device,
- g_strerror (errno_save));
-
- return FALSE;
- }
- else
- backend_egl->fb_device_id = fd;
-
- backend_egl->egl_surface =
- eglCreateWindowSurface (edpy,
- config,
- (NativeWindowType) backend_egl->fb_device_id,
- NULL);
- }
- else
- {
- backend_egl->egl_surface =
- eglCreateWindowSurface (edpy,
- config,
- (NativeWindowType) NULL,
- 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;
- }
-
- CLUTTER_NOTE (BACKEND, "Setting context");
-
- /* Without X we assume we 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);
-
-#endif /* COGL_HAS_XLIB_SUPPORT */
+ g_atexit (clutter_backend_at_exit);
return TRUE;
-
-fail:
-
- /* NB: We currently only support a single fallback option */
- if (retry_cookie == 0)
- {
- retry_cookie = 1;
- goto retry;
- }
-
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "%s", error_message);
-
- return FALSE;
-}
-
-static void
-clutter_backend_egl_ensure_context (ClutterBackend *backend,
- ClutterStage *stage)
-{
-#ifndef COGL_HAS_XLIB_SUPPORT
- /* Without X we only have one EGL surface to worry about
- * so we can assume it is permanently made current and
- * don't have to do anything here. */
-#else
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- ClutterStageWindow *impl;
-
- if (stage == NULL ||
- CLUTTER_ACTOR_IN_DESTRUCTION (stage) ||
- ((impl = _clutter_stage_get_window (stage)) == NULL))
- {
- CLUTTER_NOTE (BACKEND, "Clearing EGL context");
- eglMakeCurrent (backend_egl->edpy,
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- }
- else
- {
- ClutterStageEGL *stage_egl;
- ClutterStageX11 *stage_x11;
-
- g_assert (impl != NULL);
-
- CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
- g_type_name (G_OBJECT_TYPE (impl)),
- impl);
-
- stage_egl = CLUTTER_STAGE_EGL (impl);
- stage_x11 = CLUTTER_STAGE_X11 (impl);
-
- if (backend_egl->egl_context == EGL_NO_CONTEXT)
- return;
-
- clutter_x11_trap_x_errors ();
-
- /* we might get here inside the final dispose cycle, so we
- * need to handle this gracefully
- */
- if (stage_x11->xwin == None ||
- stage_egl->egl_surface == EGL_NO_SURFACE)
- {
- CLUTTER_NOTE (MULTISTAGE,
- "Received a stale stage, clearing all context");
-
- if (backend_egl->dummy_surface == EGL_NO_SURFACE)
- eglMakeCurrent (backend_egl->edpy,
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- else
- eglMakeCurrent (backend_egl->edpy,
- backend_egl->dummy_surface,
- backend_egl->dummy_surface,
- backend_egl->egl_context);
- }
- else
- {
- CLUTTER_NOTE (MULTISTAGE, "Setting real surface current");
- eglMakeCurrent (backend_egl->edpy,
- stage_egl->egl_surface,
- stage_egl->egl_surface,
- backend_egl->egl_context);
- }
-
- if (clutter_x11_untrap_x_errors ())
- g_critical ("Unable to make the stage window 0x%x the current "
- "EGLX drawable",
- (int) stage_x11->xwin);
- }
-#endif /* COGL_HAS_XLIB_SUPPORT */
}
#ifndef COGL_HAS_XLIB_SUPPORT
static void
clutter_backend_egl_dispose (GObject *gobject)
{
+ ClutterBackend *backend = CLUTTER_BACKEND (gobject);
+#ifdef HAVE_TSLIB
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
-#ifdef COGL_HAS_X11_SUPPORT
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
-#else
- ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage);
#endif
- /* We chain up before disposing our own resources so that
- ClutterBackendX11 will destroy all of the stages before we
- destroy the egl context. Otherwise the actors may try to make GL
- calls during destruction which causes a crash */
+ /* We chain up before disposing our CoglContext so that we will
+ * destroy all of the stages first. Otherwise the actors may try to
+ * make Cogl calls during destruction which would cause a crash */
G_OBJECT_CLASS (_clutter_backend_egl_parent_class)->dispose (gobject);
-#ifdef HAVE_TSLIB
- /* XXX: This should be renamed to _clutter_events_tslib_uninit */
- _clutter_events_egl_uninit (backend_egl);
-#endif
-
-#ifdef COGL_HAS_XLIB_SUPPORT
- if (backend_egl->dummy_surface != EGL_NO_SURFACE)
- {
- eglDestroySurface (backend_egl->edpy, backend_egl->dummy_surface);
- backend_egl->dummy_surface = EGL_NO_SURFACE;
- }
-
- if (backend_egl->dummy_xwin)
- {
- XDestroyWindow (backend_x11->xdpy, backend_egl->dummy_xwin);
- backend_egl->dummy_xwin = None;
- }
-
-#else /* COGL_HAS_XLIB_SUPPORT */
-
- if (backend_egl->egl_surface != EGL_NO_SURFACE)
- {
- eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
- backend_egl->egl_surface = EGL_NO_SURFACE;
- }
-
- if (backend_egl->stage != NULL)
- {
- clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper));
- backend_egl->stage = NULL;
- }
-
- if (backend_egl->fb_device_id != -1)
+ if (backend->cogl_context)
{
- close (backend_egl->fb_device_id);
- backend_egl->fb_device_id = -1;
- }
-
-#endif /* COGL_HAS_XLIB_SUPPORT */
-
- if (backend_egl->egl_context)
- {
- eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
- backend_egl->egl_context = NULL;
- }
-
- if (backend_egl->edpy)
- {
- eglTerminate (backend_egl->edpy);
- backend_egl->edpy = 0;
+ cogl_object_unref (backend->cogl_context);
+ backend->cogl_context = NULL;
}
#ifdef HAVE_TSLIB
+ /* XXX: This should be renamed to _clutter_events_tslib_uninit */
+ _clutter_events_egl_uninit (backend_egl);
+
if (backend_egl->event_timer != NULL)
{
g_timer_destroy (backend_egl->event_timer);
return g_object_ref (backend_singleton);
}
-static gboolean
-check_vblank_env (const char *name)
-{
- if (clutter_vblank_name && !g_ascii_strcasecmp (clutter_vblank_name, name))
- return TRUE;
-
- return FALSE;
-}
-
static ClutterFeatureFlags
clutter_backend_egl_get_features (ClutterBackend *backend)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- const gchar *egl_extensions = NULL;
- const gchar *gl_extensions = NULL;
- ClutterFeatureFlags flags;
-
- g_assert (backend_egl->egl_context != NULL);
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterBackendClass *parent_class;
+#endif
+ ClutterFeatureFlags flags = 0;
#ifdef COGL_HAS_XLIB_SUPPORT
- {
- ClutterBackendClass *parent_class;
+ parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
- parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
- flags = parent_class->get_features (backend);
- flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
- }
-#else
- flags = CLUTTER_FEATURE_STAGE_STATIC;
+ flags = parent_class->get_features (backend);
#endif
- /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
- if (check_vblank_env ("none"))
- backend_egl->vblank_type = CLUTTER_VBLANK_NONE;
+ if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
+ {
+ CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers");
+ flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
+ }
else
- backend_egl->vblank_type = CLUTTER_VBLANK_SWAP_INTERVAL;
-
- egl_extensions = eglQueryString (backend_egl->edpy, EGL_EXTENSIONS);
+ {
+ CLUTTER_NOTE (BACKEND, "Cogl only supports one onscreen framebuffer");
+ flags |= CLUTTER_FEATURE_STAGE_STATIC;
+ }
- if (cogl_clutter_check_extension ("EGL_NOK_swap_region", egl_extensions))
+ if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
{
- CLUTTER_NOTE (BACKEND,
- "Using EGL_NOK_swap_region for sub_buffer copies");
- backend_egl->swap_buffers_region =
- (void *)cogl_get_proc_address ("eglSwapBuffersRegionNOK");
- backend_egl->can_blit_sub_buffer = TRUE;
- backend_egl->blit_sub_buffer_is_synchronized = TRUE;
+ CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
+ flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
}
+ else
+ CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
- gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS);
+ if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
+ {
+ CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
+ flags |= CLUTTER_FEATURE_SWAP_EVENTS;
+ }
-#if 0 /* XXX need GL_ARB_draw_buffers */
- if (!backend_egl->swap_buffers_region &&
- cogl_clutter_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
+ if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
{
- CLUTTER_NOTE (BACKEND,
- "Using glBlitFramebuffer fallback for sub_buffer copies");
- backend_egl->blit_framebuffer =
- (BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer");
+ CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
backend_egl->can_blit_sub_buffer = TRUE;
- backend_egl->blit_sub_buffer_is_synchronized = FALSE;
}
+
+ return flags;
+}
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+static XVisualInfo *
+clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
+{
+ return cogl_clutter_winsys_xlib_get_visual_info ();
+}
#endif
- CLUTTER_NOTE (BACKEND, "Checking features\n"
- "GL_VENDOR: %s\n"
- "GL_RENDERER: %s\n"
- "GL_VERSION: %s\n"
- "EGL_VENDOR: %s\n"
- "EGL_VERSION: %s\n"
- "EGL_EXTENSIONS: %s\n",
- glGetString (GL_VENDOR),
- glGetString (GL_RENDERER),
- glGetString (GL_VERSION),
- eglQueryString (backend_egl->edpy, EGL_VENDOR),
- eglQueryString (backend_egl->edpy, EGL_VERSION),
- eglQueryString (backend_egl->edpy, EGL_EXTENSIONS));
+static gboolean
+clutter_backend_egl_create_context (ClutterBackend *backend,
+ GError **error)
+{
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+#endif
+ CoglSwapChain *swap_chain = NULL;
+ CoglOnscreenTemplate *onscreen_template = NULL;
- return flags;
+ if (backend->cogl_context)
+ return TRUE;
+
+ backend->cogl_renderer = cogl_renderer_new ();
+#ifdef COGL_HAS_XLIB_SUPPORT
+ cogl_renderer_xlib_set_foreign_display (backend->cogl_renderer,
+ backend_x11->xdpy);
+#endif
+ if (!cogl_renderer_connect (backend->cogl_renderer, error))
+ goto error;
+
+ swap_chain = cogl_swap_chain_new ();
+#ifdef COGL_HAS_XLIB_SUPPORT
+ cogl_swap_chain_set_has_alpha (swap_chain,
+ clutter_x11_get_use_argb_visual ());
+#endif
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
+ cogl_swap_chain_set_length (swap_chain, gdl_n_buffers);
+#endif
+
+ onscreen_template = cogl_onscreen_template_new (swap_chain);
+ cogl_object_unref (swap_chain);
+
+ /* XXX: I have some doubts that this is a good design.
+ * Conceptually should we be able to check an onscreen_template
+ * without more details about the CoglDisplay configuration?
+ */
+ if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
+ onscreen_template,
+ error))
+ goto error;
+
+ backend->cogl_display = cogl_display_new (backend->cogl_renderer,
+ onscreen_template);
+
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
+ cogl_display_cex100_set_gdl_plane (backend->cogl_display, gdl_plane);
+#endif
+
+ cogl_object_unref (backend->cogl_renderer);
+ cogl_object_unref (onscreen_template);
+
+ if (!cogl_display_setup (backend->cogl_display, error))
+ goto error;
+
+ backend->cogl_context = cogl_context_new (backend->cogl_display, error);
+ if (!backend->cogl_context)
+ goto error;
+
+ /* XXX: eventually this should go away but a lot of Cogl code still
+ * depends on a global default context. */
+ cogl_set_default_context (backend->cogl_context);
+
+ return TRUE;
+
+error:
+ if (backend->cogl_display)
+ {
+ cogl_object_unref (backend->cogl_display);
+ backend->cogl_display = NULL;
+ }
+
+ if (onscreen_template)
+ cogl_object_unref (onscreen_template);
+ if (swap_chain)
+ cogl_object_unref (swap_chain);
+
+ if (backend->cogl_renderer)
+ {
+ cogl_object_unref (backend->cogl_renderer);
+ backend->cogl_renderer = NULL;
+ }
+ return FALSE;
}
static ClutterStageWindow *
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
- "The EGL native backend does not support multiple stages");
+ "The Cogl backend does not support multiple "
+ "onscreen windows");
return backend_egl->stage;
}
return stage;
}
-#ifdef COGL_HAS_XLIB_SUPPORT
-static XVisualInfo *
-clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
+static void
+clutter_backend_egl_ensure_context (ClutterBackend *backend,
+ ClutterStage *stage)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend_x11);
- XVisualInfo visinfo_template;
- int template_mask = 0;
- XVisualInfo *visinfo = NULL;
- int visinfos_count;
- EGLint visualid, red_size, green_size, blue_size, alpha_size;
-
- if (!clutter_backend_egl_create_context (CLUTTER_BACKEND (backend_x11), NULL))
- return NULL;
-
- visinfo_template.screen = backend_x11->xscreen_num;
- template_mask |= VisualScreenMask;
-
- eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
- EGL_NATIVE_VISUAL_ID, &visualid);
-
- if (visualid != 0)
- {
- visinfo_template.visualid = visualid;
- template_mask |= VisualIDMask;
- }
- else
- {
- /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
- * attribute, so attempt to find the closest match. */
-
- eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
- EGL_RED_SIZE, &red_size);
- eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
- EGL_GREEN_SIZE, &green_size);
- eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
- EGL_BLUE_SIZE, &blue_size);
- eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
- EGL_ALPHA_SIZE, &alpha_size);
-
- visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
- template_mask |= VisualDepthMask;
- }
+ ClutterStageEGL *stage_egl =
+ CLUTTER_STAGE_EGL (_clutter_stage_get_window (stage));
- visinfo = XGetVisualInfo (backend_x11->xdpy,
- template_mask,
- &visinfo_template,
- &visinfos_count);
-
- return visinfo;
+ cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_egl->onscreen));
}
-#endif
static void
_clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
static void
_clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
{
-#ifndef COGL_HAS_XLIB_SUPPORT
-
#ifdef HAVE_TSLIB
backend_egl->event_timer = g_timer_new ();
#endif
-
- backend_egl->fb_device_id = -1;
-
-#else
-
- backend_egl->egl_context = EGL_NO_CONTEXT;
- backend_egl->dummy_surface = EGL_NO_SURFACE;
-
-#endif
}
-#ifdef CLUTTER_EGL_BACKEND_GENERIC
GType
_clutter_backend_impl_get_type (void)
{
return _clutter_backend_egl_get_type ();
}
-#endif
EGLDisplay
clutter_eglx_display (void)
return 0;
}
- return backend_singleton->edpy;
+ return cogl_context_egl_get_egl_display (backend_singleton->cogl_context);
+}
+
+/* FIXME we should have a CLUTTER_ define for this */
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
+void
+clutter_cex100_set_plane (gdl_plane_id_t plane)
+{
+ g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
+
+ gdl_plane = plane;
+}
+
+void
+clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
+{
+ g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
+ mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
+
+ gdl_n_buffers = mode;
}
+#endif
typedef struct _ClutterBackendEGL ClutterBackendEGL;
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
-typedef enum ClutterEGLVBlankType {
- CLUTTER_VBLANK_NONE = 0,
- CLUTTER_VBLANK_SWAP_INTERVAL
-} ClutterEGLVBlankType;
-
-typedef void (*BlitFramebufferProc) (GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1,
- GLbitfield mask,
- GLenum filter);
-
-typedef EGLBoolean (*SwapBuffersRegionProc) (EGLDisplay dpy,
- EGLSurface surface,
- EGLint numRects,
- const EGLint *rects);
struct _ClutterBackendEGL
{
#ifdef COGL_HAS_XLIB_SUPPORT
ClutterBackendX11 parent_instance;
- /* EGL Specific */
- EGLDisplay edpy;
- EGLContext egl_context;
- EGLConfig egl_config;
-
- Window dummy_xwin;
- EGLSurface dummy_surface;
-
#else /* COGL_HAS_X11_SUPPORT */
-
ClutterBackend parent_instance;
- /* EGL Specific */
- EGLDisplay edpy;
- EGLSurface egl_surface;
- EGLContext egl_context;
-
- /* from the backend */
- gint surface_width;
- gint surface_height;
-
/* main stage singleton */
ClutterStageWindow *stage;
/* event timer */
GTimer *event_timer;
- /* FB device */
- gint fb_device_id;
-
#endif /* COGL_HAS_X11_SUPPORT */
- gint egl_version_major;
- gint egl_version_minor;
-
- ClutterEGLVBlankType vblank_type;
+ CoglContext *cogl_context;
- gboolean can_blit_sub_buffer;
- BlitFramebufferProc blit_framebuffer;
- SwapBuffersRegionProc swap_buffers_region;
- gboolean blit_sub_buffer_is_synchronized;
+ gboolean can_blit_sub_buffer;
};
struct _ClutterBackendEGLClass
void _clutter_events_egl_init (ClutterBackendEGL *backend);
void _clutter_events_egl_uninit (ClutterBackendEGL *backend);
-void
-_clutter_backend_egl_blit_sub_buffer (ClutterBackendEGL *backend_egl,
- EGLSurface drawable,
- int x, int y, int width, int height);
+G_CONST_RETURN gchar*
+_clutter_backend_egl_get_vblank (void);
G_END_DECLS
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
-#ifdef COGL_HAS_XLIB_SUPPORT
-
static void
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
- ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
CLUTTER_NOTE (BACKEND, "Unrealizing EGL stage [%p]", stage_egl);
- clutter_x11_trap_x_errors ();
-
- if (stage_egl->egl_surface != EGL_NO_SURFACE)
- {
- eglDestroySurface (clutter_egl_get_egl_display (), stage_egl->egl_surface);
- stage_egl->egl_surface = EGL_NO_SURFACE;
- }
-
- _clutter_stage_x11_destroy_window_untrapped (stage_x11);
-
- XSync (backend_x11->xdpy, False);
+#ifdef COGL_HAS_XLIB_SUPPORT
+ /* chain up to the StageX11 implementation */
+ clutter_stage_window_parent_iface->unrealize (stage_window);
+#endif
- clutter_x11_untrap_x_errors ();
+ cogl_object_unref (stage_egl->onscreen);
+ stage_egl->onscreen = NULL;
}
static gboolean
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
{
- ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
- ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
- ClutterBackend *backend;
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+#endif
+ ClutterBackend *backend;
ClutterBackendEGL *backend_egl;
- EGLDisplay edpy;
+ CoglFramebuffer *framebuffer;
+ GError *error = NULL;
+ gfloat width = 800;
+ gfloat height = 600;
+ const char *clutter_vblank;
CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
G_OBJECT_TYPE_NAME (stage_egl),
backend = clutter_get_default_backend ();
backend_egl = CLUTTER_BACKEND_EGL (backend);
- edpy = clutter_egl_get_egl_display ();
+#ifdef COGL_HAS_XLIB_SUPPORT
+ clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
+#endif
- if (!_clutter_stage_x11_create_window (stage_x11))
- return FALSE;
+ stage_egl->onscreen = cogl_onscreen_new (backend->cogl_context,
+ width, height);
+#ifdef COGL_HAS_XLIB_SUPPORT
+ if (stage_x11->xwin != None)
+ cogl_onscreen_x11_set_foreign_window_xid (stage_egl->onscreen,
+ stage_x11->xwin);
+#endif
+
+ clutter_vblank = _clutter_backend_egl_get_vblank ();
+ if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
+ cogl_onscreen_set_swap_throttled (stage_egl->onscreen, FALSE);
- if (stage_egl->egl_surface == EGL_NO_SURFACE)
+ framebuffer = COGL_FRAMEBUFFER (stage_egl->onscreen);
+ if (!cogl_framebuffer_allocate (framebuffer, &error))
{
- stage_egl->egl_surface =
- eglCreateWindowSurface (edpy,
- backend_egl->egl_config,
- (NativeWindowType) stage_x11->xwin,
- NULL);
+ g_warning ("Failed to allocate stage: %s", error->message);
+ g_error_free (error);
+ cogl_object_unref (stage_egl->onscreen);
+ stage_egl->onscreen = NULL;
+ return FALSE;
}
+ /* FIXME: for fullscreen EGL platforms then the size we gave above
+ * will be ignored, so we need to make sure the stage size is
+ * updated to this size. */
- if (stage_egl->egl_surface == EGL_NO_SURFACE)
- g_warning ("Unable to create an EGL surface");
+#ifdef COGL_HAS_XLIB_SUPPORT
+ if (stage_x11->xwin == None)
+ stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_egl->onscreen);
return clutter_stage_egl_parent_iface->realize (stage_window);
+#else
+ return TRUE;
+#endif
}
-#else /* COGL_HAS_XLIB_SUPPORT */
+#ifndef COGL_HAS_XLIB_SUPPORT
-static void
-clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
-{
-}
-
-static gboolean
-clutter_stage_egl_realize (ClutterStageWindow *stage_window)
-{
- /* the EGL surface is created by the backend */
- return TRUE;
-}
+/* FIXME: Move this warnings up into clutter-stage.c */
static void
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
ClutterGeometry *geometry)
{
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
- ClutterBackendEGL *backend_egl = stage_egl->backend;
if (geometry)
{
- geometry->x = geometry->y = 0;
+ if (stage_egl->onscreen)
+ {
+ CoglFramebuffer *framebuffer =
+ COGL_FRAMEBUFFER (stage_egl->onscreen);
+
+ geometry->x = geometry->y = 0;
- geometry->width = backend_egl->surface_width;
- geometry->height = backend_egl->surface_height;
+ geometry->width = cogl_framebuffer_get_width (framebuffer);
+ geometry->height = cogl_framebuffer_get_height (framebuffer);
+ }
+ else
+ {
+ geometry->x = geometry->y = 0;
+ geometry->width = 800;
+ geometry->height = 600;
+ }
}
}
stage_egl->initialized_redraw_clip = TRUE;
}
+/* XXX: This is basically identical to clutter_stage_glx_redraw */
static void
clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
{
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
- ClutterBackend *backend = clutter_get_default_backend ();
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
ClutterActor *wrapper;
- EGLSurface egl_surface;
+ ClutterBackend *backend;
+ ClutterBackendEGL *backend_egl;
gboolean may_use_clipped_redraw;
gboolean use_clipped_redraw;
+
+ CLUTTER_STATIC_TIMER (painting_timer,
+ "Redrawing", /* parent */
+ "Painting actors",
+ "The time spent painting actors",
+ 0 /* no application private data */);
+ CLUTTER_STATIC_TIMER (swapbuffers_timer,
+ "Redrawing", /* parent */
+ "eglSwapBuffers",
+ "The time spent blocked by eglSwapBuffers",
+ 0 /* no application private data */);
+ CLUTTER_STATIC_TIMER (blit_sub_buffer_timer,
+ "Redrawing", /* parent */
+ "egl_blit_sub_buffer",
+ "The time spent in _egl_blit_sub_buffer",
+ 0 /* no application private data */);
+
#ifdef COGL_HAS_X11_SUPPORT
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
- egl_surface = stage_egl->egl_surface;
#else
wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
- /* Without X we only support one surface and that is associated
- * with the backend directly instead of the stage */
- egl_surface = backend_egl->egl_surface;
#endif
+ if (!stage_egl->onscreen)
+ return;
+
+ backend = clutter_get_default_backend ();
+ backend_egl = CLUTTER_BACKEND_EGL (backend);
+
+ CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
+
if (G_LIKELY (backend_egl->can_blit_sub_buffer) &&
- /* NB: a zero width clip == full stage redraw */
+ /* NB: a zero width redraw clip == full stage redraw */
stage_egl->bounding_redraw_clip.width != 0 &&
/* some drivers struggle to get going and produce some junk
* frames when starting up... */
&& G_LIKELY (stage_x11->clipped_redraws_cool_off == 0)
#endif
)
- may_use_clipped_redraw = TRUE;
+ {
+ may_use_clipped_redraw = TRUE;
+ }
else
may_use_clipped_redraw = FALSE;
else
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
- if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS &&
- may_use_clipped_redraw)
+ if (may_use_clipped_redraw &&
+ G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
{
- ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
static CoglMaterial *outline = NULL;
+ ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
+ ClutterActor *actor = CLUTTER_ACTOR (wrapper);
CoglHandle vbo;
float x_1 = clip->x;
float x_2 = clip->x + clip->width;
cogl_push_matrix ();
cogl_matrix_init_identity (&modelview);
- _clutter_actor_apply_modelview_transform (wrapper, &modelview);
+ _clutter_actor_apply_modelview_transform (actor, &modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source (outline);
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
cogl_object_unref (vbo);
}
- cogl_flush ();
+ CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
/* push on the screen */
if (use_clipped_redraw)
{
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
- ClutterGeometry copy_area;
+ int copy_area[4];
+ ClutterActor *actor;
+
+ /* XXX: It seems there will be a race here in that the stage
+ * window may be resized before the cogl_framebuffer_swap_region
+ * is handled and so we may copy the wrong region. I can't
+ * really see how we can handle this with the current state of X
+ * but at least in this case a full redraw should be queued by
+ * the resize anyway so it should only exhibit temporary
+ * artefacts.
+ */
+
+ actor = CLUTTER_ACTOR (wrapper);
+ copy_area[0] = clip->x;
+ copy_area[1] = clutter_actor_get_height (actor) - clip->y - clip->height;
+ copy_area[2] = clip->width;
+ copy_area[3] = clip->height;
CLUTTER_NOTE (BACKEND,
- "_egl_blit_sub_buffer (surface: %p, "
- "x: %d, y: %d, "
- "width: %d, height: %d)",
- egl_surface,
- stage_egl->bounding_redraw_clip.x,
- stage_egl->bounding_redraw_clip.y,
- stage_egl->bounding_redraw_clip.width,
- stage_egl->bounding_redraw_clip.height);
-
- copy_area.x = clip->x;
- copy_area.y = clip->y;
- copy_area.width = clip->width;
- copy_area.height = clip->height;
+ "cogl_framebuffer_swap_region (onscreen: %p, "
+ "x: %d, y: %d, "
+ "width: %d, height: %d)",
+ stage_egl->onscreen,
+ copy_area[0], copy_area[1], copy_area[2], copy_area[3]);
+
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
- _clutter_backend_egl_blit_sub_buffer (backend_egl,
- egl_surface,
- copy_area.x,
- copy_area.y,
- copy_area.width,
- copy_area.height);
+
+ cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_egl->onscreen),
+ copy_area, 1);
+
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
}
else
{
- CLUTTER_NOTE (BACKEND, "eglwapBuffers (display: %p, surface: %p)",
- backend_egl->edpy,
- egl_surface);
+ CLUTTER_NOTE (BACKEND, "cogl_framebuffer_swap_buffers (onscreen: %p)",
+ stage_egl->onscreen);
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
- eglSwapBuffers (backend_egl->edpy, egl_surface);
+ cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_egl->onscreen));
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
}
gobject_class->dispose = clutter_stage_egl_dispose;
}
-
-static void
-_clutter_stage_egl_init (ClutterStageEGL *stage)
-{
- stage->egl_surface = EGL_NO_SURFACE;
-}
-
-#else /* COGL_HAS_X11_SUPPORT */
-
+#else
static void
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
{
}
+#endif /* COGL_HAS_X11_SUPPORT */
static void
_clutter_stage_egl_init (ClutterStageEGL *stage)
{
- /* Without X we only support one surface and that is associated
- * with the backend directly instead of the stage */
}
-
-#endif /* COGL_HAS_X11_SUPPORT */
ClutterStageX11 parent_instance;
- EGLSurface egl_surface;
-
#else
GObject parent_instance;
#endif
+ CoglOnscreen *onscreen;
+
/* We only enable clipped redraws after 2 frames, since we've seen
* a lot of drivers can struggle to get going and may output some
* junk frames to start with. */
{
ClutterBackendX11 parent_instance;
- int error_base;
- int event_base;
+ CoglContext *cogl_context;
- CoglContext *cogl_context;
-
- /* Vblank stuff */
- ClutterGLXVBlankType vblank_type;
- unsigned int last_video_sync_count;
-
- gboolean can_blit_sub_buffer;
+ gboolean can_blit_sub_buffer;
/* props */
Atom atom_WM_STATE;
}
void
-_clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11)
-{
- Window xwin = stage_x11->xwin;
-
- if (clutter_stages_by_xid != NULL)
- {
- CLUTTER_NOTE (BACKEND, "Removing X11 stage 0x%x [%p]",
- (unsigned int) xwin,
- stage_x11);
-
- g_hash_table_remove (clutter_stages_by_xid, GINT_TO_POINTER (xwin));
- }
-
- if (!stage_x11->is_foreign_xwin && xwin != None)
- {
- ClutterBackendX11 *backend_x11 = stage_x11->backend;
-
- g_assert (clutter_stages_by_xid != NULL);
-
- XDestroyWindow (backend_x11->xdpy, xwin);
- stage_x11->xwin = None;
- }
- else
- stage_x11->xwin = None;
-}
-
-void
-_clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11)
-{
- if (stage_x11->xwin == None)
- return;
-
- clutter_x11_trap_x_errors ();
-
- _clutter_stage_x11_destroy_window_untrapped (stage_x11);
-
- clutter_x11_untrap_x_errors ();
-}
-
-gboolean
-_clutter_stage_x11_create_window (ClutterStageX11 *stage_x11)
-{
- ClutterBackendX11 *backend_x11 = stage_x11->backend;
- XSetWindowAttributes xattr;
- XVisualInfo *xvisinfo;
- unsigned long mask;
- gfloat width, height;
-
- if (stage_x11->xwin != None)
- return TRUE;
-
- CLUTTER_NOTE (MISC, "Creating stage X window");
-
- xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
- if (xvisinfo == NULL)
- {
- g_critical ("Unable to find suitable GL visual.");
- return FALSE;
- }
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (backend_x11->xdpy,
- backend_x11->xscreen_num);
- xattr.border_pixel = 0;
- xattr.colormap = XCreateColormap (backend_x11->xdpy,
- backend_x11->xwin_root,
- xvisinfo->visual,
- AllocNone);
- mask = CWBorderPixel | CWColormap;
-
- /* Call get_size - this will either get the geometry size (which
- * before we create the window is set to 640x480), or if a size
- * is set, it will get that. This lets you set a size on the
- * stage before it's realized.
- *
- * we also round to the nearest integer because stage sizes
- * should always be in pixels
- */
- clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
- stage_x11->xwin_width = floorf (width + 0.5);
- stage_x11->xwin_height = floorf (height + 0.5);
-
- stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
- backend_x11->xwin_root,
- 0, 0,
- stage_x11->xwin_width,
- stage_x11->xwin_height,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
- stage_x11,
- (unsigned int) stage_x11->xwin,
- stage_x11->xwin_width,
- stage_x11->xwin_height);
-
- XFree (xvisinfo);
-
- return TRUE;
-}
-
-void
_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
guint32 user_time)
{
GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
/* Private to subclasses */
-gboolean _clutter_stage_x11_create_window (ClutterStageX11 *stage_x11);
-void _clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11);
-void _clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11);
void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
guint32 user_time);
gboolean _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
+ AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
+
AC_CHECK_HEADERS([GL/glx.h],
[],
[AC_MSG_ERROR([Unable to locate required GLX headers])])
[
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT], [1],
[Cogl supports OpenGL[ES] using the EGL API with PowerVR X11 platform typedefs])
+ AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
])
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"],
[
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT], [1],
[Cogl supports OpenGL[ES] using the EGL API with PowerVR NULL platform typedefs])
+ AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
])
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_GDL" = "x1"],