diff --git a/ChangeLog b/ChangeLog index 777c250ec..67d3c3672 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2007-07-06 Matthew Allum + + * clutter/Makefile.am: + * clutter/eglnative/Makefile.am: + * clutter/eglnative/clutter-backend-egl.c: + * clutter/eglnative/clutter-backend-egl.h: + * clutter/eglnative/clutter-egl.h: + * clutter/eglnative/clutter-event-egl.c: + * clutter/eglnative/clutter-stage-egl.c: + * clutter/eglnative/clutter-stage-egl.h: + * clutter/eglx/Makefile.am: + * clutter/eglx/clutter-backend-egl.c: + * clutter/eglx/clutter-egl.h: + * clutter/eglx/clutter-event-egl.c: + * clutter/eglx/clutter-stage-egl.c: + * configure.ac: + Add a new 'native' EGL backend for non X based EGL's + (i.e on framebuffer). + Rename old backend to 'eglx' and namespace public funcs with this. + + * clutter/pango/pangoclutter-private.h: + Add extra checks for expected defines. + 2007-07-06 Matthew Allum * NEWS: diff --git a/clutter/Makefile.am b/clutter/Makefile.am index d6fb37692..4081f9791 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -2,7 +2,7 @@ NULL = SUBDIRS = cogl pango $(clutterbackend) -DIST_SUBDIRS = pango glx egl cogl sdl +DIST_SUBDIRS = pango glx eglx eglnative cogl sdl target = $(clutterbackend) diff --git a/clutter/eglnative/Makefile.am b/clutter/eglnative/Makefile.am new file mode 100644 index 000000000..8d23aa2df --- /dev/null +++ b/clutter/eglnative/Makefile.am @@ -0,0 +1,19 @@ +libclutterincludedir = $(includedir)/clutter-@CLUTTER_MAJORMINOR@/clutter + +INCLUDES = \ + -DG_LOG_DOMAIN=\"ClutterEGL\" \ + -I$(top_srcdir) \ + $(CLUTTER_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(GCC_FLAGS) + +LDADD = $(CLUTTER_LIBS) + +noinst_LTLIBRARIES = libclutter-eglnative.la + +libclutter_eglnative_la_SOURCES = \ + clutter-backend-egl.h \ + clutter-backend-egl.c \ + clutter-event-egl.c \ + clutter-stage-egl.h \ + clutter-stage-egl.c diff --git a/clutter/eglnative/clutter-backend-egl.c b/clutter/eglnative/clutter-backend-egl.c new file mode 100644 index 000000000..d83aba690 --- /dev/null +++ b/clutter/eglnative/clutter-backend-egl.c @@ -0,0 +1,212 @@ +#include "config.h" + +#include "clutter-backend-egl.h" +#include "clutter-stage-egl.h" +#include "../clutter-private.h" +#include "../clutter-main.h" +#include "../clutter-debug.h" + +static ClutterBackendEGL *backend_singleton = NULL; + + +G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND); + +static gboolean +clutter_backend_egl_pre_parse (ClutterBackend *backend, + GError **error) +{ + return TRUE; +} + +static gboolean +clutter_backend_egl_post_parse (ClutterBackend *backend, + GError **error) +{ + backend_egl->edpy = eglGetDisplay(backend_egl->xdpy); + + status = eglInitialize(backend_egl->edpy, + &backend_egl->egl_version_major, + &backend_egl->egl_version_minor); + + 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; +} + +static gboolean +clutter_backend_egl_init_stage (ClutterBackend *backend, + GError **error) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + + if (!backend_egl->stage) + { + ClutterStageEGL *stage_egl; + ClutterActor *stage; + + stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL); + + g_object_set_data (G_OBJECT (stage), "clutter-backend", backend); + + backend_egl->stage = g_object_ref_sink (stage); + } + + clutter_actor_realize (backend_egl->stage); + if (!CLUTTER_ACTOR_IS_REALIZED (backend_egl->stage)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_INTERNAL, + "Unable to realize the main stage"); + return FALSE; + } + + return TRUE; +} + +static void +clutter_backend_egl_init_events (ClutterBackend *backend) +{ + _clutter_events_init (backend); + +} + +static const GOptionEntry entries[] = +{ + { NULL } +}; + +static void +clutter_backend_egl_redraw (ClutterBackend *backend) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + ClutterStageEGL *stage_egl; + + stage_egl = CLUTTER_STAGE_EGL(backend_egl->stage); + + clutter_actor_paint (CLUTTER_ACTOR(stage_egl)); + + /* Why this paint is done in backend as likely GL windowing system + * specific calls, like swapping buffers. + */ + if (stage_egl->xwin) + { + /* clutter_feature_wait_for_vblank (); */ + eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface); + } + else + { + eglWaitGL (); + CLUTTER_GLERR (); + } +} + +static ClutterActor * +clutter_backend_egl_get_stage (ClutterBackend *backend) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + + return backend_egl->stage; +} + +static void +clutter_backend_egl_finalize (GObject *gobject) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject); + + if (backend_singleton) + backend_singleton = NULL; + + G_OBJECT_CLASS (clutter_backend_egl_parent_class)->finalize (gobject); +} + +static void +clutter_backend_egl_dispose (GObject *gobject) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject); + + _clutter_events_uninit (CLUTTER_BACKEND (backend_egl)); + + if (backend_egl->stage) + { + g_object_unref (backend_egl->stage); + backend_egl->stage = NULL; + } + + G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject); +} + +static GObject * +clutter_backend_egl_constructor (GType gtype, + guint n_params, + GObjectConstructParam *params) +{ + GObjectClass *parent_class; + GObject *retval; + + if (!backend_singleton) + { + parent_class = G_OBJECT_CLASS (clutter_backend_egl_parent_class); + retval = parent_class->constructor (gtype, n_params, params); + + backend_singleton = CLUTTER_BACKEND_EGL (retval); + + return retval; + } + + g_warning ("Attempting to create a new backend object. This should " + "never happen, so we return the singleton instance."); + + return g_object_ref (backend_singleton); +} + +static void +clutter_backend_egl_class_init (ClutterBackendEGLClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); + + gobject_class->constructor = clutter_backend_egl_constructor; + gobject_class->dispose = clutter_backend_egl_dispose; + gobject_class->finalize = clutter_backend_egl_finalize; + + backend_class->pre_parse = clutter_backend_egl_pre_parse; + backend_class->post_parse = clutter_backend_egl_post_parse; + backend_class->init_stage = clutter_backend_egl_init_stage; + backend_class->init_events = clutter_backend_egl_init_events; + backend_class->get_stage = clutter_backend_egl_get_stage; + backend_class->add_options = clutter_backend_egl_add_options; + backend_class->redraw = clutter_backend_egl_redraw; +} + +static void +clutter_backend_egl_init (ClutterBackendEGL *backend_egl) +{ + ClutterBackend *backend = CLUTTER_BACKEND (backend_egl); + + clutter_backend_set_double_click_time (backend, 250); + clutter_backend_set_double_click_distance (backend, 5); +} + +GType +_clutter_backend_impl_get_type (void) +{ + return clutter_backend_egl_get_type (); +} + +EGLDisplay +clutter_egl_display (void) +{ + return (EGLDisplay)clutter_egl_get_default_display (); +} diff --git a/clutter/eglnative/clutter-backend-egl.h b/clutter/eglnative/clutter-backend-egl.h new file mode 100644 index 000000000..5b0cbdc2e --- /dev/null +++ b/clutter/eglnative/clutter-backend-egl.h @@ -0,0 +1,72 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_BACKEND_EGL_H__ +#define __CLUTTER_BACKEND_EGL_H__ + +#include +#include + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_EGL (clutter_backend_egl_get_type ()) +#define CLUTTER_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGL)) +#define CLUTTER_IS_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL)) +#define CLUTTER_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGLClass)) +#define CLUTTER_IS_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL)) +#define CLUTTER_BACKEND_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGLClass)) + +typedef struct _ClutterBackendEGL ClutterBackendEGL; +typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass; + +struct _ClutterBackendEGL +{ + ClutterBackend parent_instance; + + /* EGL Specific */ + EGLDisplay edpy; + gint egl_version_major, egl_version_minor; + + /* main stage singleton */ + ClutterActor *stage; + + /* event source */ + GSource *event_source; + + /*< private >*/ +}; + +struct _ClutterBackendEGLClass +{ + ClutterBackendClass parent_class; +}; + +GType clutter_backend_egl_get_type (void) G_GNUC_CONST; + +void _clutter_events_init (ClutterBackend *backend); +void _clutter_events_uninit (ClutterBackend *backend); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_EGL_H__ */ diff --git a/clutter/eglnative/clutter-egl.h b/clutter/eglnative/clutter-egl.h new file mode 100644 index 000000000..3e591bae2 --- /dev/null +++ b/clutter/eglnative/clutter-egl.h @@ -0,0 +1,43 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_EGL_H__ +#define __CLUTTER_EGL_H__ + +#include + +#include +#include + +#include + +G_BEGIN_DECLS + +EGLDisplay +clutter_egl_display (void); + +G_END_DECLS + +#endif /* __CLUTTER_EGL_H__ */ diff --git a/clutter/eglnative/clutter-event-egl.c b/clutter/eglnative/clutter-event-egl.c new file mode 100644 index 000000000..cffd3f25b --- /dev/null +++ b/clutter/eglnative/clutter-event-egl.c @@ -0,0 +1,121 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "clutter-stage-egl.h" +#include "clutter-backend-egl.h" +#include "clutter-egl.h" + +#include "../clutter-backend.h" +#include "../clutter-event.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" +#include "../clutter-main.h" + +#include + +#include + +typedef struct _ClutterEventSource ClutterEventSource; + +struct _ClutterEventSource +{ + GSource source; + + ClutterBackend *backend; + GPollFD event_poll_fd; +}; + +static gboolean clutter_event_prepare (GSource *source, + gint *timeout); +static gboolean clutter_event_check (GSource *source); +static gboolean clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static GList *event_sources = NULL; + +static GSourceFuncs event_funcs = { + clutter_event_prepare, + clutter_event_check, + clutter_event_dispatch, + NULL +}; + +static GSource * +clutter_event_source_new (ClutterBackend *backend) +{ + GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); + ClutterEventSource *event_source = (ClutterEventSource *) source; + + event_source->backend = backend; + + return source; +} + +void +_clutter_events_init (ClutterBackend *backend) +{ + GSource *source; + ClutterEventSource *event_source; + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); +#if 0 + int connection_number; + + connection_number = ConnectionNumber (backend_egl->xdpy); + CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number); + + source = backend_egl->event_source = clutter_event_source_new (backend); + event_source = (ClutterEventSource *) source; + g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); + + event_source->event_poll_fd.fd = connection_number; + event_source->event_poll_fd.events = G_IO_IN; + + event_sources = g_list_prepend (event_sources, event_source); + + g_source_add_poll (source, &event_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); +#endif +} + +void +_clutter_events_uninit (ClutterBackend *backend) +{ + ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + + if (backend_egl->event_source) + { +#if 0 + CLUTTER_NOTE (EVENT, "Destroying the event source"); + + event_sources = g_list_remove (event_sources, + backend_egl->event_source); + + g_source_destroy (backend_egl->event_source); + g_source_unref (backend_egl->event_source); +#endif + backend_egl->event_source = NULL; + } +} + diff --git a/clutter/eglnative/clutter-stage-egl.c b/clutter/eglnative/clutter-stage-egl.c new file mode 100644 index 000000000..5caee0fd7 --- /dev/null +++ b/clutter/eglnative/clutter-stage-egl.c @@ -0,0 +1,263 @@ +#include "config.h" + +#include "clutter-stage-egl.h" +#include "clutter-egl.h" + +#include "../clutter-main.h" +#include "../clutter-feature.h" +#include "../clutter-color.h" +#include "../clutter-util.h" +#include "../clutter-event.h" +#include "../clutter-enum-types.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" +#include "../clutter-units.h" + +G_DEFINE_TYPE (ClutterStageEGL, clutter_stage_egl, CLUTTER_TYPE_STAGE); + +/* NOTE: EGL implementation needs to provide this function */ +extern NativeWindowType createNativeWindow(void); + +static void +clutter_stage_egl_show (ClutterActor *actor) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); + + /* we are always shown... */ + + return; +} + +static void +clutter_stage_egl_hide (ClutterActor *actor) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); + + /* we are always shown... */ + + return; +} + +static void +clutter_stage_egl_unrealize (ClutterActor *actor) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); + gboolean was_offscreen; + + CLUTTER_MARK(); + + g_object_get (actor, "offscreen", &was_offscreen, NULL); + + if (stage_egl->egl_surface) + eglDestroySurface (clutter_egl_display(), stage_egl->egl_surface); + stage_egl->egl_surface = NULL; + + if (stage_egl->egl_context) + eglDestroyContext (clutter_egl_display(), stage_egl->egl_context); + stage_egl->egl_context = NULL; + + eglMakeCurrent (clutter_egl_display(), + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + stage_egl->egl_context = EGL_NO_CONTEXT; +} + +static void +clutter_stage_egl_realize (ClutterActor *actor) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); + + EGLConfig configs[2]; + EGLint config_count; + EGLBoolean status; + ClutterPerspective perspective; + + gboolean is_offscreen; + + CLUTTER_NOTE (BACKEND, "Realizing main stage"); + + g_object_get (actor, "offscreen", &is_offscreen, NULL); + + if (G_LIKELY (!is_offscreen)) + { + NativeWindowType window; + + EGLint cfg_attribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE, + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_DEPTH_SIZE, 16, + EGL_ALPHA_SIZE, EGL_DONT_CARE, + EGL_STENCIL_SIZE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE }; + + status = eglGetConfigs (clutter_egl_display(), + configs, + 2, + &config_count); + + if (status != EGL_TRUE) + g_warning ("eglGetConfigs"); + + status = eglChooseConfig (clutter_egl_display(), + cfg_attribs, + configs, + sizeof configs / sizeof configs[0], + &config_count); + + if (status != EGL_TRUE) + g_warning ("eglChooseConfig"); + + if (stage_egl->egl_context) + eglDestroyContext (clutter_egl_display(), stage_egl->egl_context); + + if (stage_egl->egl_surface) + eglDestroySurface (clutter_egl_display(), stage_egl->egl_surface); + + /* EGL Implementation needs to provide createNativeWindow() */ + window = createNativeWindow(); + + stage_egl->egl_surface + = eglCreateWindowSurface (clutter_egl_display(), + configs[0], + window, + NULL); + + eglQuerySurface (clutter_egl_display(), + stage_egl->egl_surface, + EGL_WIDTH, + &stage_egl->surface_width); + + eglQuerySurface (clutter_egl_display(), + stage_egl->egl_surface, + EGL_HEIGHT, + &stage_egl->surface_height); + + if (stage_egl->egl_surface == EGL_NO_SURFACE) + g_warning ("eglCreateWindowSurface"); + + CLUTTER_NOTE (BACKEND, "surface is %ix%i", + stage_egl->surface_width, stage_egl->surface_height); + + stage_egl->egl_context = eglCreateContext (clutter_egl_display(), + configs[0], + EGL_NO_CONTEXT, + NULL); + + if (stage_egl->egl_context == EGL_NO_CONTEXT) + g_warning ("eglCreateContext"); + + status = eglMakeCurrent (clutter_egl_display(), + stage_egl->egl_surface, + stage_egl->egl_surface, + stage_egl->egl_context); + + if (status != EGL_TRUE) + g_warning ("eglMakeCurrent"); + } + else + { + /* FIXME */ + } + + clutter_stage_get_perspectivex (CLUTTER_STAGE (actor), &perspective); + cogl_setup_viewport (clutter_actor_get_width (actor), + clutter_actor_get_height (actor), + perspective.fovy, + perspective.aspect, + perspective.z_near, + perspective.z_far); +} + +static void +clutter_stage_egl_query_coords (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self); + + box->x1 = box->y1 = 0; + box->x2 = box->x1 + CLUTTER_UNITS_FROM_INT (stage_egl->surface_width); + box->y2 = box->y1 + CLUTTER_UNITS_FROM_INT (stage_egl->surface_height); +} + +static void +clutter_stage_egl_request_coords (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self); + + /* framebuffer no resize */ + box->x1 = 0; + box->y1 = 0; + box->x2 = CLUTTER_UNITS_FROM_INT (stage_egl->surface_width); + box->y2 = CLUTTER_UNITS_FROM_INT (stage_egl->surface_height); +} + +static void +clutter_stage_egl_set_fullscreen (ClutterStage *stage, + gboolean fullscreen) +{ + g_warning ("Stage of type `%s' do not support ClutterStage::set_fullscreen", + G_OBJECT_TYPE_NAME (stage)); +} + + +static void +clutter_stage_egl_set_offscreen (ClutterStage *stage, + gboolean offscreen) +{ + g_warning ("Stage of type `%s' do not support ClutterStage::set_offscreen", + G_OBJECT_TYPE_NAME (stage)); +} + +static GdkPixbuf* +clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage, + gint x, + gint y, + gint width, + gint height) +{ + g_warning ("Stage of type `%s' do not support ClutterStage::draw_to_pixbuf", + G_OBJECT_TYPE_NAME (stage)); + return NULL; +} + +static void +clutter_stage_egl_dispose (GObject *gobject) +{ + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject); + + clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl)); + + G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject); +} + +static void +clutter_stage_egl_class_init (ClutterStageEGLClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass); + + gobject_class->dispose = clutter_stage_egl_dispose; + + actor_class->show = clutter_stage_egl_show; + actor_class->hide = clutter_stage_egl_hide; + actor_class->realize = clutter_stage_egl_realize; + actor_class->unrealize = clutter_stage_egl_unrealize; + actor_class->request_coords = clutter_stage_egl_request_coords; + actor_class->query_coords = clutter_stage_egl_query_coords; + + stage_class->set_fullscreen = clutter_stage_egl_set_fullscreen; + stage_class->set_offscreen = clutter_stage_egl_set_offscreen; + stage_class->draw_to_pixbuf = clutter_stage_egl_draw_to_pixbuf; +} + +static void +clutter_stage_egl_init (ClutterStageEGL *stage) +{ + ; +} + + diff --git a/clutter/eglnative/clutter-stage-egl.h b/clutter/eglnative/clutter-stage-egl.h new file mode 100644 index 000000000..4b4491f34 --- /dev/null +++ b/clutter/eglnative/clutter-stage-egl.h @@ -0,0 +1,38 @@ +#ifndef __CLUTTER_STAGE_EGL_H__ +#define __CLUTTER_STAGE_EGL_H__ + +#include +#include +#include +#include + +#define CLUTTER_TYPE_STAGE_EGL (clutter_stage_egl_get_type ()) +#define CLUTTER_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGL)) +#define CLUTTER_IS_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_EGL)) +#define CLUTTER_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGLClass)) +#define CLUTTER_IS_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_EGL)) +#define CLUTTER_STAGE_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGLClass)) + +typedef struct _ClutterStageEGL ClutterStageEGL; +typedef struct _ClutterStageEGLClass ClutterStageEGLClass; + +struct _ClutterStageEGL +{ + ClutterStage parent_instance; + + /* from the backend */ + gint surface_width; + gint surface_height; + + EGLSurface egl_surface; + EGLContext egl_context; +}; + +struct _ClutterStageEGLClass +{ + ClutterStageClass parent_class; +}; + +GType clutter_stage_egl_get_type (void) G_GNUC_CONST; + +#endif /* __CLUTTER_STAGE_EGL_H__ */ diff --git a/clutter/eglx/Makefile.am b/clutter/eglx/Makefile.am index 547911fee..c93b79cd3 100644 --- a/clutter/eglx/Makefile.am +++ b/clutter/eglx/Makefile.am @@ -9,9 +9,9 @@ INCLUDES = \ LDADD = $(CLUTTER_LIBS) -noinst_LTLIBRARIES = libclutter-egl.la +noinst_LTLIBRARIES = libclutter-eglx.la -libclutter_egl_la_SOURCES = \ +libclutter_eglx_la_SOURCES = \ clutter-backend-egl.h \ clutter-backend-egl.c \ clutter-event-egl.c \ diff --git a/clutter/eglx/clutter-backend-egl.c b/clutter/eglx/clutter-backend-egl.c index 8cb070364..a5133e2df 100644 --- a/clutter/eglx/clutter-backend-egl.c +++ b/clutter/eglx/clutter-backend-egl.c @@ -305,21 +305,21 @@ error_handler(Display *xdpy, } /** - * clutter_egl_trap_x_errors: + * clutter_eglx_trap_x_errors: * * FIXME * * Since: 0.4 */ void -clutter_egl_trap_x_errors (void) +clutter_eglx_trap_x_errors (void) { TrappedErrorCode = 0; old_error_handler = XSetErrorHandler (error_handler); } /** - * clutter_egl_untrap_x_errors: + * clutter_eglx_untrap_x_errors: * * FIXME * @@ -328,7 +328,7 @@ clutter_egl_trap_x_errors (void) * Since: 0.4 */ gint -clutter_egl_untrap_x_errors (void) +clutter_eglx_untrap_x_errors (void) { XSetErrorHandler (old_error_handler); @@ -336,7 +336,7 @@ clutter_egl_untrap_x_errors (void) } /** - * clutter_egl_get_default_display: + * clutter_eglx_get_default_xdisplay: * * Returns the default X Display * @@ -345,7 +345,7 @@ clutter_egl_untrap_x_errors (void) * Since: 0.4 */ Display * -clutter_egl_get_default_display (void) +clutter_eglx_get_default_xdisplay (void) { if (!backend_singleton) { @@ -357,7 +357,7 @@ clutter_egl_get_default_display (void) } /** - * clutter_egl_get_default_screen: + * clutter_eglx_get_default_screen: * * FIXME * @@ -366,7 +366,7 @@ clutter_egl_get_default_display (void) * Since: 0.4 */ gint -clutter_egl_get_default_screen (void) +clutter_eglx_get_default_screen (void) { if (!backend_singleton) { @@ -378,7 +378,7 @@ clutter_egl_get_default_screen (void) } /** - * clutter_egl_get_default_root_window: + * clutter_eglx_get_default_root_window: * * FIXME * @@ -387,7 +387,7 @@ clutter_egl_get_default_screen (void) * Since: 0.4 */ Window -clutter_egl_get_default_root_window (void) +clutter_eglx_get_default_root_window (void) { if (!backend_singleton) { @@ -408,7 +408,7 @@ clutter_egl_get_default_root_window (void) * Since: 0.4 */ EGLDisplay -clutter_egl_display (void) +clutter_eglx_display (void) { return backend_singleton->edpy; } diff --git a/clutter/eglx/clutter-egl.h b/clutter/eglx/clutter-egl.h index 784783a02..4d6306b73 100644 --- a/clutter/eglx/clutter-egl.h +++ b/clutter/eglx/clutter-egl.h @@ -39,21 +39,21 @@ G_BEGIN_DECLS -void clutter_egl_trap_x_errors (void); -gint clutter_egl_untrap_x_errors (void); +void clutter_eglx_trap_x_errors (void); +gint clutter_eglx_untrap_x_errors (void); -Display *clutter_egl_get_default_display (void); -gint clutter_egl_get_default_screen (void); -Window clutter_egl_get_default_root_window (void); +Display *clutter_eglx_get_default_xdisplay (void); +gint clutter_eglx_get_default_screen (void); +Window clutter_eglx_get_default_root_window (void); -Window clutter_egl_get_stage_window (ClutterStage *stage); -XVisualInfo *clutter_egl_get_stage_visual (ClutterStage *stage); +Window clutter_eglx_get_stage_window (ClutterStage *stage); +XVisualInfo *clutter_eglx_get_stage_visual (ClutterStage *stage); -void clutter_egl_set_stage_foreign (ClutterStage *stage, - Window window); +void clutter_eglx_set_stage_foreign (ClutterStage *stage, + Window window); EGLDisplay -clutter_egl_display (void); +clutter_eglx_display (void); G_END_DECLS diff --git a/clutter/eglx/clutter-event-egl.c b/clutter/eglx/clutter-event-egl.c index 4ddccaabd..57ff5eab1 100644 --- a/clutter/eglx/clutter-event-egl.c +++ b/clutter/eglx/clutter-event-egl.c @@ -178,7 +178,7 @@ clutter_event_translate (ClutterBackend *backend, backend_egl = CLUTTER_BACKEND_EGL (backend); stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend)); - stage_xwindow = clutter_egl_get_stage_window (stage); + stage_xwindow = clutter_eglx_get_stage_window (stage); xwindow = xevent->xany.window; if (xwindow == None) diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c index b80061f8d..df5cecfde 100644 --- a/clutter/eglx/clutter-stage-egl.c +++ b/clutter/eglx/clutter-stage-egl.c @@ -68,14 +68,14 @@ clutter_stage_egl_unrealize (ClutterActor *actor) } if (stage_egl->egl_surface) - eglDestroySurface (clutter_egl_display(), stage_egl->egl_surface); + eglDestroySurface (clutter_eglx_display(), stage_egl->egl_surface); stage_egl->egl_surface = NULL; if (stage_egl->egl_context) - eglDestroyContext (clutter_egl_display(), stage_egl->egl_context); + eglDestroyContext (clutter_eglx_display(), stage_egl->egl_context); stage_egl->egl_context = NULL; - eglMakeCurrent (clutter_egl_display(), + eglMakeCurrent (clutter_eglx_display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); stage_egl->egl_context = None; @@ -105,7 +105,7 @@ clutter_stage_egl_realize (ClutterActor *actor) EGL_BLUE_SIZE, 5, EGL_NONE }; - status = eglGetConfigs (clutter_egl_display(), + status = eglGetConfigs (clutter_eglx_display(), configs, 2, &config_count); @@ -113,7 +113,7 @@ clutter_stage_egl_realize (ClutterActor *actor) if (status != EGL_TRUE) g_warning ("eglGetConfigs"); - status = eglChooseConfig (clutter_egl_display(), + status = eglChooseConfig (clutter_eglx_display(), cfg_attribs, configs, sizeof configs / sizeof configs[0], @@ -124,16 +124,16 @@ clutter_stage_egl_realize (ClutterActor *actor) if (stage_egl->xwin == None) stage_egl->xwin - = XCreateSimpleWindow(clutter_egl_get_default_display(), - clutter_egl_get_default_root_window(), + = XCreateSimpleWindow(clutter_eglx_get_default_xdisplay(), + clutter_eglx_get_default_root_window(), 0, 0, stage_egl->xwin_width, stage_egl->xwin_height, 0, 0, - WhitePixel(clutter_egl_get_default_display(), - clutter_egl_get_default_screen())); + WhitePixel(clutter_eglx_get_default_xdisplay(), + clutter_eglx_get_default_screen())); - XSelectInput(clutter_egl_get_default_display(), + XSelectInput(clutter_eglx_get_default_xdisplay(), stage_egl->xwin, StructureNotifyMask |ExposureMask @@ -146,13 +146,13 @@ clutter_stage_egl_realize (ClutterActor *actor) |PropertyChangeMask); if (stage_egl->egl_context) - eglDestroyContext (clutter_egl_display(), stage_egl->egl_context); + eglDestroyContext (clutter_eglx_display(), stage_egl->egl_context); if (stage_egl->egl_surface) - eglDestroySurface (clutter_egl_display(), stage_egl->egl_surface); + eglDestroySurface (clutter_eglx_display(), stage_egl->egl_surface); stage_egl->egl_surface - = eglCreateWindowSurface (clutter_egl_display(), + = eglCreateWindowSurface (clutter_eglx_display(), configs[0], (NativeWindowType)stage_egl->xwin, NULL); @@ -160,7 +160,7 @@ clutter_stage_egl_realize (ClutterActor *actor) if (stage_egl->egl_surface == EGL_NO_SURFACE) g_warning ("eglCreateWindowSurface"); - stage_egl->egl_context = eglCreateContext (clutter_egl_display(), + stage_egl->egl_context = eglCreateContext (clutter_eglx_display(), configs[0], EGL_NO_CONTEXT, NULL); @@ -168,7 +168,7 @@ clutter_stage_egl_realize (ClutterActor *actor) if (stage_egl->egl_context == EGL_NO_CONTEXT) g_warning ("eglCreateContext"); - status = eglMakeCurrent (clutter_egl_display(), + status = eglMakeCurrent (clutter_eglx_display(), stage_egl->egl_surface, EGL_NO_SURFACE, stage_egl->egl_context); @@ -382,7 +382,7 @@ clutter_stage_egl_init (ClutterStageEGL *stage) } /** - * clutter_egl_get_stage_window: + * clutter_eglx_get_stage_window: * @stage: a #ClutterStage * * FIXME @@ -392,7 +392,7 @@ clutter_stage_egl_init (ClutterStageEGL *stage) * Since: 0.4 */ Window -clutter_egl_get_stage_window (ClutterStage *stage) +clutter_eglx_get_stage_window (ClutterStage *stage) { g_return_val_if_fail (CLUTTER_IS_STAGE_EGL (stage), None); @@ -400,7 +400,7 @@ clutter_egl_get_stage_window (ClutterStage *stage) } /** - * clutter_egl_get_stage_visual: + * clutter_eglx_get_stage_visual: * @stage: a #ClutterStage * * FIXME @@ -410,7 +410,7 @@ clutter_egl_get_stage_window (ClutterStage *stage) * Since: 0.4 */ XVisualInfo * -clutter_egl_get_stage_visual (ClutterStage *stage) +clutter_eglx_get_stage_visual (ClutterStage *stage) { g_return_val_if_fail (CLUTTER_IS_STAGE_EGL (stage), NULL); @@ -418,7 +418,7 @@ clutter_egl_get_stage_visual (ClutterStage *stage) } /** - * clutter_egl_set_stage_foreign: + * clutter_eglx_set_stage_foreign: * @stage: a #ClutterStage * @window: FIXME * @@ -427,7 +427,7 @@ clutter_egl_get_stage_visual (ClutterStage *stage) * Since: 0.4 */ void -clutter_egl_set_stage_foreign (ClutterStage *stage, +clutter_eglx_set_stage_foreign (ClutterStage *stage, Window window) { g_return_if_fail (CLUTTER_IS_STAGE_EGL (stage)); diff --git a/clutter/pango/pangoclutter-private.h b/clutter/pango/pangoclutter-private.h index 1d375e7d7..4e3933955 100644 --- a/clutter/pango/pangoclutter-private.h +++ b/clutter/pango/pangoclutter-private.h @@ -26,7 +26,20 @@ #include #include -/* Defines duped */ +/* Defines duped - fun,fun.. */ + +#ifndef PANGO_GLYPH_EMPTY +#define PANGO_GLYPH_EMPTY ((PangoGlyph)0x0FFFFFFF) +#endif +#ifndef PANGO_GLYPH_UNKNOWN_FLAG +#define PANGO_GLYPH_UNKNOWN_FLAG ((PangoGlyph)0x10000000) +#endif +#ifndef PANGO_UNKNOWN_GLYPH_WIDTH +#define PANGO_UNKNOWN_GLYPH_WIDTH 10 +#endif +#ifndef PANGO_UNKNOWN_GLYPH_HEIGHT +#define PANGO_UNKNOWN_GLYPH_HEIGHT 14 +#endif #define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) diff --git a/configure.ac b/configure.ac index 35a8d60c4..3afab160c 100644 --- a/configure.ac +++ b/configure.ac @@ -74,25 +74,6 @@ AC_CHECK_FUNCS([memset munmap strcasecmp strdup]) dnl ======================================================================== -PKG_CHECK_MODULES(X11, x11, [have_x11=yes], [have_x11=no]) -if test x$have_x11 = xno -then - AC_PATH_X - if test x"$x_includes" != x"NONE" && test -n "$x_includes" ; then - X11_CFLAGS=-I`echo $x_includes | sed -e "s/:/ -I/g"` - fi - if test x"$x_libraries" != x"NONE" && test -n "$x_libraries" ; then - X11_LIBS=-L`echo $x_libraries | sed -e "s/:/ -L/g"` - fi -fi - -PKG_CHECK_MODULES(XFIXES, xfixes >= 4, [have_xfixes=yes], [have_xfixes=no]) -if test x$have_xfixes = xyes -then - AC_DEFINE(HAVE_XFIXES, 1, Have the XFIXES X extension) - X11_LIBS="$X11_LIBS -lXfixes" -fi - CLUTTER_NO_FPU="0" AC_ARG_WITH(fpu, AS_HELP_STRING([--without-fpu], @@ -108,12 +89,36 @@ AC_SUBST(CLUTTER_NO_FPU) clutterbackend=glx AC_ARG_WITH([flavour], - AC_HELP_STRING([--with-flavour=@<:@glx/eglx/sdl@:>@], + AC_HELP_STRING([--with-flavour=@<:@glx/eglx/eglnative/sdl@:>@], [Select the Clutter backend]), clutterbackend=$with_flavour) BACKEND_PC_FILES="" +# Check for X though could be redundant if backend does not need it. +PKG_CHECK_MODULES(X11, x11, [have_x11=yes], [have_x11=no]) +if test x$have_x11 = xno; then + AC_PATH_X + if test x"$no_x" = "yes" ; then + if test "x$clutterbackend" = "xglx" or "x$clutterbackend" = "xeglx" + then + AC_MSG_ERROR([[No X11 Libraries found and required by backend.]]) + fi + fi + if test x"$x_includes" != x"NONE" && test -n "$x_includes" ; then + X11_CFLAGS=-I`echo $x_includes | sed -e "s/:/ -I/g"` + fi + if test x"$x_libraries" != x"NONE" && test -n "$x_libraries" ; then + X11_LIBS=-L`echo $x_libraries | sed -e "s/:/ -L/g"` + fi +fi + +PKG_CHECK_MODULES(XFIXES, xfixes >= 4, [have_xfixes=yes], [have_xfixes=no]) +if test x$have_xfixes = xyes; then + AC_DEFINE(HAVE_XFIXES, 1, Have the XFIXES X extension) + X11_LIBS="$X11_LIBS -lXfixes" +fi + case $clutterbackend in sdl) @@ -200,16 +205,49 @@ case $clutterbackend in CLUTTER_COGL="gles" AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering]) + # try for libvincent first PKG_CHECK_MODULES(EGL, libvincent, HAVE_OGLES=yes, HAVE_OGLES=no) if test "x$HAVE_OGLES" = "xno"; then - AC_MSG_ERROR([libvincent (ogles) not found and egl backend requested.]); + AC_CHECK_HEADERS([GLES/egl.h GLES/gl.h],, + [AC_MSG_ERROR([Unable to locate required GLES headers])]) + + AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no) + + if test "x$HAVE_LIBGLES" = "xno"; then + AC_MSG_ERROR([GLES library not found and egl backend requested.]); + fi + + EGL_LIBS="-lGLES_CM" fi EGL_LIBS="$EGL_LIBS $X11_LIBS" EGL_CFLAGS="$EGL_CFLAGS $X11_CFLAGS" ;; - *) AC_MSG_ERROR([Invalid backend for Clutter: use glx,sdl or eglx]) + eglnative) + + CLUTTER_FLAVOUR="eglnative" + AC_DEFINE([HAVE_CLUTTER_EGL], 1, [Have the EGL backend]) + + # We currently assume having egl means also having gles.. + CLUTTER_COGL="gles" + AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering]) + + AC_CHECK_HEADERS([GLES/egl.h GLES/gl.h],, + [AC_MSG_ERROR([Unable to locate required GLES headers])]) + + AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no) + + if test "x$HAVE_LIBGLES" = "xno"; then + AC_MSG_ERROR([libGLES_CM not found and egl backend requested.]); + fi + + EGL_LIBS="-lGLES_CM" + EGL_CFLAGS="" + ;; + + + *) AC_MSG_ERROR([Invalid backend for Clutter: use glx,sdl, eglx or eglnative]) ;; esac @@ -297,7 +335,8 @@ AC_CONFIG_FILES([ clutter/Makefile clutter/clutter-version.h clutter/glx/Makefile - clutter/egl/Makefile + clutter/eglx/Makefile + clutter/eglnative/Makefile clutter/sdl/Makefile clutter/cogl/Makefile clutter/cogl/gl/Makefile