Compare commits
	
		
			1 Commits
		
	
	
		
			gbsneto/of
			...
			wip/smcv/c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2efd0dfc06 | 
							
								
								
									
										27
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,30 +1,3 @@ | ||||
| 3.37.2 | ||||
| ====== | ||||
| * Fix move-to-center keybinding with multiple monitors [Sergey; #1073] | ||||
| * Fix stuck buttons when a virtual device is destroyed [Carlos; !1239] | ||||
| * Use workarea when centering new windows [Akatsuki; #964] | ||||
| * Limit mipmap levels when rendering background [Daniel; !1003] | ||||
| * Broadcast clipboard/primary offers [Carlos; !1253] | ||||
| * Support primary-selection protocol from wayland-protocols [Carlos; !1255] | ||||
| * Fix monitor screen cast on X11 [Jonas Å.; !1251] | ||||
| * Support a "blank" cursor type [Florian; !1244] | ||||
| * Improve stage view damage tracking [Jonas Å.; !1237] | ||||
| * Implement touch-mode detecation for the X11 backend [Carlos; !1278] | ||||
| * Drop external keyboard detection from touch-mode heuristics [Carlos; !1277] | ||||
| * Optimize actor allocations [Jonas D.; !1247] | ||||
| * Fixed crashes [Daniel, Carlos, Jonas Å., Jonas D.; !1256, !1258, !1217, !1280] | ||||
| * Misc. bug fixes and cleanups [Christian, Jonas D., Olivier, Ting-Wei, | ||||
|   Jonas Å., Marco, Corentin, Daniel, Robert, Niels, Florian, Simon; !1231, | ||||
|   !1228, !1238, !1229, !1192, !1236, !1171, !1134, #1126, !1234, !1230, !1210, | ||||
|   !1242, !1243, !1252, !1113, !1232, !1259, !1245, !1265, !1180, !1261, !788, | ||||
|   !1264, !1235, !1218, !1150, !1274, !1271, !1279, !1283, !1272] | ||||
|  | ||||
| Contributors: | ||||
|   Marco Trevisan (Treviño), Akatsuki, Jonas Dreßler, Olivier Fourdan, | ||||
|   Carlos Garnacho, Niels De Graef, Ting-Wei Lan, Robert Mader, Simon McVittie, | ||||
|   Florian Müllner, Corentin Noël, Christian Rauch, Daniel van Vugt, | ||||
|   Sergey Zigachev, Jonas Ådahl | ||||
|  | ||||
| 3.37.1 | ||||
| ====== | ||||
| * Fix screencasting non-maximized windows [Jonas Å.; !1174] | ||||
|   | ||||
							
								
								
									
										147
									
								
								clutter/clutter/cally/cally-group.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								clutter/clutter/cally/cally-group.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| /* CALLY - The Clutter Accessibility Implementation Library | ||||
|  * | ||||
|  * Copyright (C) 2008 Igalia, S.L. | ||||
|  * | ||||
|  * Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com> | ||||
|  * | ||||
|  * Based on GailContainer from GAIL | ||||
|  * Copyright 2001, 2002, 2003 Sun Microsystems Inc. | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:cally-group | ||||
|  * @Title: CallyGroup | ||||
|  * @short_description: Implementation of the ATK interfaces for a #ClutterGroup | ||||
|  * @see_also: #ClutterGroup | ||||
|  * | ||||
|  * #CallyGroup implements the required ATK interfaces of #ClutterGroup | ||||
|  * In particular it exposes each of the Clutter actors contained in the | ||||
|  * group. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "cally-group.h" | ||||
| #include "cally-actor-private.h" | ||||
|  | ||||
| static gint       cally_group_get_n_children  (AtkObject *obj); | ||||
| static AtkObject* cally_group_ref_child       (AtkObject *obj, | ||||
|                                               gint       i); | ||||
| static void       cally_group_real_initialize (AtkObject *obj, | ||||
|                                               gpointer   data); | ||||
|  | ||||
| G_DEFINE_TYPE (CallyGroup, cally_group, CALLY_TYPE_ACTOR) | ||||
|  | ||||
| static void | ||||
| cally_group_class_init (CallyGroupClass *klass) | ||||
| { | ||||
| /*   GObjectClass   *gobject_class = G_OBJECT_CLASS (klass); */ | ||||
|   AtkObjectClass *class         = ATK_OBJECT_CLASS (klass); | ||||
|  | ||||
|   class->get_n_children = cally_group_get_n_children; | ||||
|   class->ref_child      = cally_group_ref_child; | ||||
|   class->initialize     = cally_group_real_initialize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cally_group_init (CallyGroup      *group) | ||||
| { | ||||
|   /* nothing to do yet */ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * cally_group_new: | ||||
|  * @actor: a #ClutterGroup | ||||
|  * | ||||
|  * Creates a #CallyGroup for @actor | ||||
|  * | ||||
|  * Return value: the newly created #CallyGroup | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| AtkObject * | ||||
| cally_group_new (ClutterActor *actor) | ||||
| { | ||||
|   GObject   *object     = NULL; | ||||
|   AtkObject *accessible = NULL; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_GROUP (actor), NULL); | ||||
|  | ||||
|   object = g_object_new (CALLY_TYPE_GROUP, NULL); | ||||
|  | ||||
|   accessible = ATK_OBJECT (object); | ||||
|   atk_object_initialize (accessible, actor); | ||||
|  | ||||
|   return accessible; | ||||
| } | ||||
|  | ||||
| static gint | ||||
| cally_group_get_n_children (AtkObject *obj) | ||||
| { | ||||
|   ClutterActor *actor = NULL; | ||||
|   gint          count = 0; | ||||
|  | ||||
|   g_return_val_if_fail (CALLY_IS_GROUP (obj), count); | ||||
|  | ||||
|   actor = CALLY_GET_CLUTTER_ACTOR (obj); | ||||
|  | ||||
|   if (actor == NULL) /* defunct */ | ||||
|     return 0; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_GROUP(actor), count); | ||||
|  | ||||
|   count = clutter_actor_get_n_children (actor); | ||||
|  | ||||
|   return count; | ||||
| } | ||||
|  | ||||
| static AtkObject* | ||||
| cally_group_ref_child (AtkObject *obj, | ||||
|                        gint       i) | ||||
| { | ||||
|   AtkObject    *accessible = NULL; | ||||
|   ClutterActor *actor      = NULL; | ||||
|   ClutterActor *child      = NULL; | ||||
|  | ||||
|   g_return_val_if_fail (CALLY_IS_GROUP (obj), NULL); | ||||
|   g_return_val_if_fail ((i >= 0), NULL); | ||||
|  | ||||
|   actor = CALLY_GET_CLUTTER_ACTOR (obj); | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_GROUP(actor), NULL); | ||||
|   child = clutter_actor_get_child_at_index (actor, i); | ||||
|  | ||||
|   if (!child) | ||||
|     return NULL; | ||||
|  | ||||
|   accessible = clutter_actor_get_accessible (child); | ||||
|  | ||||
|   if (accessible != NULL) | ||||
|     g_object_ref (accessible); | ||||
|  | ||||
|   return accessible; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cally_group_real_initialize (AtkObject *obj, | ||||
|                             gpointer   data) | ||||
| { | ||||
|   ATK_OBJECT_CLASS (cally_group_parent_class)->initialize (obj, data); | ||||
|  | ||||
|   obj->role = ATK_ROLE_PANEL; | ||||
| } | ||||
							
								
								
									
										87
									
								
								clutter/clutter/cally/cally-group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								clutter/clutter/cally/cally-group.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* CALLY - The Clutter Accessibility Implementation Library | ||||
|  * | ||||
|  * Copyright (C) 2008 Igalia, S.L. | ||||
|  * | ||||
|  * Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com> | ||||
|  * | ||||
|  * Based on GailContainer from GAIL | ||||
|  * Copyright 2001, 2002, 2003 Sun Microsystems Inc. | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CALLY_GROUP_H__ | ||||
| #define __CALLY_GROUP_H__ | ||||
|  | ||||
| #if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <cally/cally.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <cally/cally-actor.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CALLY_TYPE_GROUP                         (cally_group_get_type ()) | ||||
| #define CALLY_GROUP(obj)                         (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_GROUP, CallyGroup)) | ||||
| #define CALLY_GROUP_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_GROUP, CallyGroupClass)) | ||||
| #define CALLY_IS_GROUP(obj)                      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_GROUP)) | ||||
| #define CALLY_IS_GROUP_CLASS(klass)              (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_GROUP)) | ||||
| #define CALLY_GROUP_GET_CLASS(obj)               (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_GROUP, CallyGroupClass)) | ||||
|  | ||||
| typedef struct _CallyGroup        CallyGroup; | ||||
| typedef struct _CallyGroupClass   CallyGroupClass; | ||||
| typedef struct _CallyGroupPrivate CallyGroupPrivate; | ||||
|  | ||||
| /** | ||||
|  * CallyGroup: | ||||
|  * | ||||
|  * The <structname>CallyGroup</structname> structure contains only | ||||
|  * private data and should be accessed using the provided API | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _CallyGroup | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActor parent; | ||||
|  | ||||
|   CallyGroupPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * CallyGroupClass: | ||||
|  * | ||||
|  * The <structname>CallyGroupClass</structname> structure contains only | ||||
|  * private data | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _CallyGroupClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   gpointer _padding_dummy[8]; | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType      cally_group_get_type (void) G_GNUC_CONST; | ||||
| CLUTTER_EXPORT | ||||
| AtkObject* cally_group_new      (ClutterActor *actor); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CALLY_GROUP_H__ */ | ||||
							
								
								
									
										98
									
								
								clutter/clutter/cally/cally-rectangle.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								clutter/clutter/cally/cally-rectangle.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| /* CALLY - The Clutter Accessibility Implementation Library | ||||
|  * | ||||
|  * Copyright (C) 2009 Igalia, S.L. | ||||
|  * | ||||
|  * Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com> | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:cally-rectangle | ||||
|  * @short_description: Implementation of the ATK interfaces for a #ClutterRectangle | ||||
|  * @see_also: #ClutterRectangle | ||||
|  * | ||||
|  * #CallyRectangle implements the required ATK interfaces of #ClutterRectangle | ||||
|  * | ||||
|  * In particular it sets a proper role for the rectangle. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #define CLUTTER_DISABLE_DEPRECATION_WARNINGS | ||||
|  | ||||
| #include "cally-rectangle.h" | ||||
| #include "cally-actor-private.h" | ||||
|  | ||||
| #include "clutter-color.h" | ||||
| #include "deprecated/clutter-rectangle.h" | ||||
|  | ||||
| /* AtkObject */ | ||||
| static void                  cally_rectangle_real_initialize (AtkObject *obj, | ||||
|                                                               gpointer   data); | ||||
|  | ||||
| G_DEFINE_TYPE (CallyRectangle, cally_rectangle, CALLY_TYPE_ACTOR) | ||||
|  | ||||
| static void | ||||
| cally_rectangle_class_init (CallyRectangleClass *klass) | ||||
| { | ||||
| /*   GObjectClass   *gobject_class = G_OBJECT_CLASS (klass); */ | ||||
|   AtkObjectClass *class         = ATK_OBJECT_CLASS (klass); | ||||
|  | ||||
|   class->initialize      = cally_rectangle_real_initialize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cally_rectangle_init (CallyRectangle *rectangle) | ||||
| { | ||||
|   /* nothing to do yet */ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * cally_rectangle_new: | ||||
|  * @actor: a #ClutterActor | ||||
|  * | ||||
|  * Creates a new #CallyRectangle for the given @actor. @actor must be | ||||
|  * a #ClutterRectangle. | ||||
|  * | ||||
|  * Return value: the newly created #AtkObject | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| AtkObject* | ||||
| cally_rectangle_new (ClutterActor *actor) | ||||
| { | ||||
|   GObject   *object     = NULL; | ||||
|   AtkObject *accessible = NULL; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_RECTANGLE (actor), NULL); | ||||
|  | ||||
|   object = g_object_new (CALLY_TYPE_RECTANGLE, NULL); | ||||
|  | ||||
|   accessible = ATK_OBJECT (object); | ||||
|   atk_object_initialize (accessible, actor); | ||||
|  | ||||
|   return accessible; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cally_rectangle_real_initialize (AtkObject *obj, | ||||
|                                  gpointer   data) | ||||
| { | ||||
|   ATK_OBJECT_CLASS (cally_rectangle_parent_class)->initialize (obj, data); | ||||
|  | ||||
|   obj->role = ATK_ROLE_IMAGE; | ||||
| } | ||||
							
								
								
									
										84
									
								
								clutter/clutter/cally/cally-rectangle.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								clutter/clutter/cally/cally-rectangle.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* CALLY - The Clutter Accessibility Implementation Library | ||||
|  * | ||||
|  * Copyright (C) 2009 Igalia, S.L. | ||||
|  * | ||||
|  * Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com> | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CALLY_RECTANGLE_H__ | ||||
| #define __CALLY_RECTANGLE_H__ | ||||
|  | ||||
| #if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <cally/cally.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <cally/cally-actor.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CALLY_TYPE_RECTANGLE            (cally_rectangle_get_type ()) | ||||
| #define CALLY_RECTANGLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_RECTANGLE, CallyRectangle)) | ||||
| #define CALLY_RECTANGLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_RECTANGLE, CallyRectangleClass)) | ||||
| #define CALLY_IS_RECTANGLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_RECTANGLE)) | ||||
| #define CALLY_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_RECTANGLE)) | ||||
| #define CALLY_RECTANGLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_RECTANGLE, CallyRectangleClass)) | ||||
|  | ||||
| typedef struct _CallyRectangle         CallyRectangle; | ||||
| typedef struct _CallyRectangleClass    CallyRectangleClass; | ||||
| typedef struct _CallyRectanglePrivate  CallyRectanglePrivate; | ||||
|  | ||||
| /** | ||||
|  * CallyRectangle: | ||||
|  * | ||||
|  * The <structname>CallyRectangle</structname> structure contains only private | ||||
|  * data and should be accessed using the provided API | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _CallyRectangle | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActor parent; | ||||
|  | ||||
|   CallyRectanglePrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * CallyRectangleClass: | ||||
|  * | ||||
|  * The <structname>CallyRectangleClass</structname> structure contains | ||||
|  * only private data | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| struct _CallyRectangleClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   gpointer _padding_dummy[8]; | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType      cally_rectangle_get_type (void) G_GNUC_CONST; | ||||
| CLUTTER_EXPORT | ||||
| AtkObject* cally_rectangle_new      (ClutterActor *actor); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CALLY_RECTANGLE_H__ */ | ||||
| @@ -63,7 +63,7 @@ struct _CallyStagePrivate | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (CallyStage, | ||||
|                          cally_stage, | ||||
|                          CALLY_TYPE_ACTOR, | ||||
|                          CALLY_TYPE_GROUP, | ||||
|                          G_ADD_PRIVATE (CallyStage) | ||||
|                          G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW, | ||||
|                                                 cally_stage_window_interface_init)); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
| #error "Only <cally/cally.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <cally/cally-actor.h> | ||||
| #include <cally/cally-group.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
| @@ -52,7 +52,7 @@ typedef struct _CallyStagePrivate CallyStagePrivate; | ||||
| struct _CallyStage | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActor parent; | ||||
|   CallyGroup parent; | ||||
|  | ||||
|   CallyStagePrivate *priv; | ||||
| }; | ||||
| @@ -68,7 +68,7 @@ struct _CallyStage | ||||
| struct _CallyStageClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   CallyActorClass parent_class; | ||||
|   CallyGroupClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   gpointer _padding_dummy[16]; | ||||
|   | ||||
| @@ -36,8 +36,10 @@ | ||||
| #include "cally.h" | ||||
|  | ||||
| #include "cally-actor.h" | ||||
| #include "cally-group.h" | ||||
| #include "cally-stage.h" | ||||
| #include "cally-text.h" | ||||
| #include "cally-rectangle.h" | ||||
| #include "cally-clone.h" | ||||
|  | ||||
| #include "cally-factory.h" | ||||
| @@ -50,8 +52,10 @@ | ||||
|  | ||||
| /* factories initialization*/ | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new) | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_GROUP, cally_group, cally_group_new) | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new) | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new) | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new) | ||||
| CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new) | ||||
|  | ||||
| /** | ||||
| @@ -69,8 +73,10 @@ cally_accessibility_init (void) | ||||
| { | ||||
|   /* setting the factories */ | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor); | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_GROUP, cally_group); | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage); | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text); | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle); | ||||
|   CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone); | ||||
|  | ||||
|   /* Initialize the CallyUtility class */ | ||||
|   | ||||
| @@ -26,7 +26,9 @@ | ||||
| #include "cally-actor.h" | ||||
| #include "cally-clone.h" | ||||
| #include "cally-factory.h" | ||||
| #include "cally-group.h" | ||||
| #include "cally-main.h" | ||||
| #include "cally-rectangle.h" | ||||
| #include "cally-root.h" | ||||
| #include "cally-stage.h" | ||||
| #include "cally-text.h" | ||||
|   | ||||
| @@ -615,32 +615,6 @@ clutter_actor_box_scale (ClutterActorBox *box, | ||||
|   box->y2 *= scale; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_actor_box_is_initialized: | ||||
|  * @box: a #ClutterActorBox | ||||
|  * | ||||
|  * Checks if @box has been initialized, a #ClutterActorBox is uninitialized | ||||
|  * if it has a size of -1 at an origin of 0, 0. | ||||
|  * | ||||
|  * Returns: %TRUE if the box is uninitialized, %FALSE if it isn't | ||||
|  */ | ||||
| gboolean | ||||
| clutter_actor_box_is_initialized (ClutterActorBox *box) | ||||
| { | ||||
|   gboolean x1_uninitialized, x2_uninitialized; | ||||
|   gboolean y1_uninitialized, y2_uninitialized; | ||||
|  | ||||
|   g_return_val_if_fail (box != NULL, TRUE); | ||||
|  | ||||
|   x1_uninitialized = isinf (box->x1); | ||||
|   x2_uninitialized = isinf (box->x2) && signbit (box->x2); | ||||
|   y1_uninitialized = isinf (box->y1); | ||||
|   y2_uninitialized = isinf (box->y2) && signbit (box->y2); | ||||
|  | ||||
|   return !x1_uninitialized || !x2_uninitialized || | ||||
|          !y1_uninitialized || !y2_uninitialized; | ||||
| } | ||||
|  | ||||
| G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box, | ||||
|                                clutter_actor_box_copy, | ||||
|                                clutter_actor_box_free, | ||||
|   | ||||
| @@ -110,12 +110,35 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor | ||||
| typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor, | ||||
|                                             gpointer      user_data); | ||||
|  | ||||
| typedef struct _AnchorCoord             AnchorCoord; | ||||
| typedef struct _SizeRequest             SizeRequest; | ||||
|  | ||||
| typedef struct _ClutterLayoutInfo       ClutterLayoutInfo; | ||||
| typedef struct _ClutterTransformInfo    ClutterTransformInfo; | ||||
| typedef struct _ClutterAnimationInfo    ClutterAnimationInfo; | ||||
|  | ||||
| /* Internal helper struct to represent a point that can be stored in | ||||
|    either direct pixel coordinates or as a fraction of the actor's | ||||
|    size. It is used for the anchor point, scale center and rotation | ||||
|    centers. */ | ||||
| struct _AnchorCoord | ||||
| { | ||||
|   gboolean is_fractional; | ||||
|  | ||||
|   union | ||||
|   { | ||||
|     /* Used when is_fractional == TRUE */ | ||||
|     struct | ||||
|     { | ||||
|       gdouble x; | ||||
|       gdouble y; | ||||
|     } fraction; | ||||
|  | ||||
|     /* Use when is_fractional == FALSE */ | ||||
|     graphene_point3d_t units; | ||||
|   } v; | ||||
| }; | ||||
|  | ||||
| struct _SizeRequest | ||||
| { | ||||
|   guint  age; | ||||
| @@ -160,15 +183,24 @@ ClutterLayoutInfo *             _clutter_actor_peek_layout_info | ||||
|  | ||||
| struct _ClutterTransformInfo | ||||
| { | ||||
|   /* rotation */ | ||||
|   /* rotation (angle and center) */ | ||||
|   gdouble rx_angle; | ||||
|   AnchorCoord rx_center; | ||||
|  | ||||
|   gdouble ry_angle; | ||||
|   AnchorCoord ry_center; | ||||
|  | ||||
|   gdouble rz_angle; | ||||
|   AnchorCoord rz_center; | ||||
|  | ||||
|   /* scaling */ | ||||
|   gdouble scale_x; | ||||
|   gdouble scale_y; | ||||
|   gdouble scale_z; | ||||
|   AnchorCoord scale_center; | ||||
|  | ||||
|   /* anchor point */ | ||||
|   AnchorCoord anchor; | ||||
|  | ||||
|   /* translation */ | ||||
|   graphene_point3d_t translation; | ||||
| @@ -281,18 +313,14 @@ void                            _clutter_actor_detach_clone | ||||
| void                            _clutter_actor_queue_redraw_on_clones                   (ClutterActor *actor); | ||||
| void                            _clutter_actor_queue_relayout_on_clones                 (ClutterActor *actor); | ||||
| void                            _clutter_actor_queue_only_relayout                      (ClutterActor *actor); | ||||
| void                            clutter_actor_clear_stage_views_recursive               (ClutterActor *actor); | ||||
| void                            _clutter_actor_queue_update_resource_scale_recursive    (ClutterActor *actor); | ||||
|  | ||||
| float                           clutter_actor_get_real_resource_scale                   (ClutterActor *actor); | ||||
| gboolean                        _clutter_actor_get_real_resource_scale                  (ClutterActor *actor, | ||||
|                                                                                          float        *resource_scale); | ||||
|  | ||||
| ClutterPaintNode *              clutter_actor_create_texture_paint_node                 (ClutterActor *self, | ||||
|                                                                                          CoglTexture  *texture); | ||||
|  | ||||
| void clutter_actor_update_stage_views (ClutterActor *self, | ||||
|                                        int           phase); | ||||
|  | ||||
| void clutter_actor_queue_immediate_relayout (ClutterActor *self); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_ACTOR_PRIVATE_H__ */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -142,6 +142,11 @@ struct _ClutterActor | ||||
|  * ClutterActorClass: | ||||
|  * @show: signal class handler for #ClutterActor::show; it must chain | ||||
|  *   up to the parent's implementation | ||||
|  * @show_all: virtual function for containers and composite actors, to | ||||
|  *   determine which children should be shown when calling | ||||
|  *   clutter_actor_show_all() on the actor. Defaults to calling | ||||
|  *   clutter_actor_show(). This virtual function is deprecated and it | ||||
|  *   should not be overridden. | ||||
|  * @hide: signal class handler for #ClutterActor::hide; it must chain | ||||
|  *   up to the parent's implementation | ||||
|  * @hide_all: virtual function for containers and composite actors, to | ||||
| @@ -178,10 +183,7 @@ struct _ClutterActor | ||||
|  *   implementation. | ||||
|  * @apply_transform: virtual function, used when applying the transformations | ||||
|  *   to an actor before painting it or when transforming coordinates or | ||||
|  *   the allocation; if the transformation calculated by this function may | ||||
|  *   have changed, the cached transformation must be invalidated by calling | ||||
|  *   clutter_actor_invalidate_transform(); it must chain up to the parent's | ||||
|  *   implementation | ||||
|  *   the allocation; it must chain up to the parent's implementation | ||||
|  * @parent_set: signal class handler for the #ClutterActor::parent-set | ||||
|  * @destroy: signal class handler for #ClutterActor::destroy. It must | ||||
|  *   chain up to the parent's implementation | ||||
| @@ -224,6 +226,7 @@ struct _ClutterActorClass | ||||
|  | ||||
|   /*< public >*/ | ||||
|   void (* show)                 (ClutterActor          *self); | ||||
|   void (* show_all)             (ClutterActor          *self); | ||||
|   void (* hide)                 (ClutterActor          *self); | ||||
|   void (* hide_all)             (ClutterActor          *self); | ||||
|   void (* realize)              (ClutterActor          *self); | ||||
| @@ -299,9 +302,6 @@ struct _ClutterActorClass | ||||
|   gboolean (* touch_event)          (ClutterActor         *self, | ||||
|                                      ClutterTouchEvent    *event); | ||||
|   gboolean (* has_accessible)       (ClutterActor         *self); | ||||
|   void     (* resource_scale_changed) (ClutterActor *self); | ||||
|   float    (* calculate_resource_scale) (ClutterActor *self, | ||||
|                                          int           phase); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   /* padding for future expansion */ | ||||
| @@ -593,7 +593,8 @@ gboolean                        clutter_actor_get_paint_box | ||||
|                                                                                  ClutterActorBox            *box); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| float                           clutter_actor_get_resource_scale                (ClutterActor *self); | ||||
| gboolean                        clutter_actor_get_resource_scale                (ClutterActor *self, | ||||
|                                                                                  gfloat       *resource_scale); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean                        clutter_actor_has_overlaps                      (ClutterActor               *self); | ||||
| @@ -918,15 +919,6 @@ void clutter_actor_pick_box (ClutterActor          *self, | ||||
|                              ClutterPickContext    *pick_context, | ||||
|                              const ClutterActorBox *box); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GList * clutter_actor_peek_stage_views (ClutterActor *self); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_actor_invalidate_transform (ClutterActor *self); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_ACTOR_H__ */ | ||||
|   | ||||
| @@ -58,7 +58,6 @@ struct _ClutterAlignConstraint | ||||
|   ClutterActor *actor; | ||||
|   ClutterActor *source; | ||||
|   ClutterAlignAxis align_axis; | ||||
|   graphene_point_t pivot; | ||||
|   gfloat factor; | ||||
| }; | ||||
|  | ||||
| @@ -73,7 +72,6 @@ enum | ||||
|  | ||||
|   PROP_SOURCE, | ||||
|   PROP_ALIGN_AXIS, | ||||
|   PROP_PIVOT_POINT, | ||||
|   PROP_FACTOR, | ||||
|  | ||||
|   PROP_LAST | ||||
| @@ -86,11 +84,12 @@ G_DEFINE_TYPE (ClutterAlignConstraint, | ||||
|                CLUTTER_TYPE_CONSTRAINT); | ||||
|  | ||||
| static void | ||||
| source_queue_relayout (ClutterActor           *actor, | ||||
|                        ClutterAlignConstraint *align) | ||||
| source_position_changed (ClutterActor           *actor, | ||||
|                          GParamSpec             *pspec, | ||||
|                          ClutterAlignConstraint *align) | ||||
| { | ||||
|   if (align->actor != NULL) | ||||
|     _clutter_actor_queue_only_relayout (align->actor); | ||||
|     clutter_actor_queue_relayout (align->actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -135,41 +134,35 @@ clutter_align_constraint_update_allocation (ClutterConstraint *constraint, | ||||
|   ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint); | ||||
|   gfloat source_width, source_height; | ||||
|   gfloat actor_width, actor_height; | ||||
|   gfloat offset_x_start, offset_y_start; | ||||
|   gfloat pivot_x, pivot_y; | ||||
|   gfloat source_x, source_y; | ||||
|  | ||||
|   if (align->source == NULL) | ||||
|     return; | ||||
|  | ||||
|   clutter_actor_box_get_size (allocation, &actor_width, &actor_height); | ||||
|  | ||||
|   clutter_actor_get_position (align->source, &source_x, &source_y); | ||||
|   clutter_actor_get_size (align->source, &source_width, &source_height); | ||||
|  | ||||
|   pivot_x = align->pivot.x == -1.f | ||||
|     ? align->factor | ||||
|     : align->pivot.x; | ||||
|   pivot_y = align->pivot.y == -1.f | ||||
|     ? align->factor | ||||
|     : align->pivot.y; | ||||
|  | ||||
|   offset_x_start = pivot_x * -actor_width; | ||||
|   offset_y_start = pivot_y * -actor_height; | ||||
|  | ||||
|   switch (align->align_axis) | ||||
|     { | ||||
|     case CLUTTER_ALIGN_X_AXIS: | ||||
|       allocation->x1 += offset_x_start + (source_width * align->factor); | ||||
|       allocation->x1 = ((source_width - actor_width) * align->factor) | ||||
|                      + source_x; | ||||
|       allocation->x2 = allocation->x1 + actor_width; | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_ALIGN_Y_AXIS: | ||||
|       allocation->y1 += offset_y_start + (source_height * align->factor); | ||||
|       allocation->y1 = ((source_height - actor_height) * align->factor) | ||||
|                      + source_y; | ||||
|       allocation->y2 = allocation->y1 + actor_height; | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_ALIGN_BOTH: | ||||
|       allocation->x1 += offset_x_start + (source_width * align->factor); | ||||
|       allocation->y1 += offset_y_start + (source_height * align->factor); | ||||
|       allocation->x1 = ((source_width - actor_width) * align->factor) | ||||
|                      + source_x; | ||||
|       allocation->y1 = ((source_height - actor_height) * align->factor) | ||||
|                      + source_y; | ||||
|       allocation->x2 = allocation->x1 + actor_width; | ||||
|       allocation->y2 = allocation->y1 + actor_height; | ||||
|       break; | ||||
| @@ -193,7 +186,7 @@ clutter_align_constraint_dispose (GObject *gobject) | ||||
|                                             G_CALLBACK (source_destroyed), | ||||
|                                             align); | ||||
|       g_signal_handlers_disconnect_by_func (align->source, | ||||
|                                             G_CALLBACK (source_queue_relayout), | ||||
|                                             G_CALLBACK (source_position_changed), | ||||
|                                             align); | ||||
|       align->source = NULL; | ||||
|     } | ||||
| @@ -219,10 +212,6 @@ clutter_align_constraint_set_property (GObject      *gobject, | ||||
|       clutter_align_constraint_set_align_axis (align, g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PIVOT_POINT: | ||||
|       clutter_align_constraint_set_pivot_point (align, g_value_get_boxed (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_FACTOR: | ||||
|       clutter_align_constraint_set_factor (align, g_value_get_float (value)); | ||||
|       break; | ||||
| @@ -251,16 +240,6 @@ clutter_align_constraint_get_property (GObject    *gobject, | ||||
|       g_value_set_enum (value, align->align_axis); | ||||
|       break; | ||||
|  | ||||
|     case PROP_PIVOT_POINT: | ||||
|       { | ||||
|         graphene_point_t point; | ||||
|  | ||||
|         clutter_align_constraint_get_pivot_point (align, &point); | ||||
|  | ||||
|         g_value_set_boxed (value, &point); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case PROP_FACTOR: | ||||
|       g_value_set_float (value, align->factor); | ||||
|       break; | ||||
| @@ -314,30 +293,6 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass) | ||||
|                        CLUTTER_ALIGN_X_AXIS, | ||||
|                        CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); | ||||
|  | ||||
|   /** | ||||
|    * ClutterAlignConstraint:pivot-point: | ||||
|    * | ||||
|    * The pivot point used by the constraint. The pivot point is the | ||||
|    * point in the constraint actor around which the aligning is applied, | ||||
|    * with (0, 0) being the top left corner of the actor and (1, 1) the | ||||
|    * bottom right corner of the actor. | ||||
|    * | ||||
|    * For example, setting the pivot point to (0.5, 0.5) and using a factor | ||||
|    * of 1 for both axes will align the actors horizontal and vertical | ||||
|    * center point with the bottom right corner of the source actor. | ||||
|    * | ||||
|    * By default, the pivot point is set to (-1, -1), which means it's not | ||||
|    * used and the constrained actor will be aligned to always stay inside | ||||
|    * the source actor. | ||||
|    */ | ||||
|   obj_props[PROP_PIVOT_POINT] = | ||||
|     g_param_spec_boxed ("pivot-point", | ||||
|                        P_("Pivot point"), | ||||
|                        P_("The pivot point"), | ||||
|                        GRAPHENE_TYPE_POINT, | ||||
|                        G_PARAM_READWRITE | | ||||
|                        G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   /** | ||||
|    * ClutterAlignConstraint:factor: | ||||
|    * | ||||
| @@ -370,8 +325,6 @@ clutter_align_constraint_init (ClutterAlignConstraint *self) | ||||
|   self->actor = NULL; | ||||
|   self->source = NULL; | ||||
|   self->align_axis = CLUTTER_ALIGN_X_AXIS; | ||||
|   self->pivot.x = -1.f; | ||||
|   self->pivot.y = -1.f; | ||||
|   self->factor = 0.0f; | ||||
| } | ||||
|  | ||||
| @@ -449,15 +402,15 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align, | ||||
|                                             G_CALLBACK (source_destroyed), | ||||
|                                             align); | ||||
|       g_signal_handlers_disconnect_by_func (old_source, | ||||
|                                             G_CALLBACK (source_queue_relayout), | ||||
|                                             G_CALLBACK (source_position_changed), | ||||
|                                             align); | ||||
|     } | ||||
|  | ||||
|   align->source = source; | ||||
|   if (align->source != NULL) | ||||
|     { | ||||
|       g_signal_connect (align->source, "queue-relayout", | ||||
|                         G_CALLBACK (source_queue_relayout), | ||||
|       g_signal_connect (align->source, "notify::allocation", | ||||
|                         G_CALLBACK (source_position_changed), | ||||
|                         align); | ||||
|       g_signal_connect (align->source, "destroy", | ||||
|                         G_CALLBACK (source_destroyed), | ||||
| @@ -534,60 +487,6 @@ clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align) | ||||
|   return align->align_axis; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_align_constraint_set_pivot_point: | ||||
|  * @align: a #ClutterAlignConstraint | ||||
|  * @pivot_point: A #GraphenePoint | ||||
|  * | ||||
|  * Sets the pivot point used by the constraint, the pivot point is the | ||||
|  * point in the constraint actor around which the aligning is applied, | ||||
|  * with (0, 0) being the top left corner of the actor and (1, 1) the | ||||
|  * bottom right corner of the actor. | ||||
|  * | ||||
|  * If -1 is used, the pivot point is unset and the constrained actor | ||||
|  * will be aligned to always stay inside the source actor. | ||||
|  */ | ||||
| void | ||||
| clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align, | ||||
|                                           const graphene_point_t *pivot_point) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align)); | ||||
|   g_return_if_fail (pivot_point != NULL); | ||||
|   g_return_if_fail (pivot_point->x == -1.f || | ||||
|                     (pivot_point->x >= 0.f && pivot_point->x <= 1.f)); | ||||
|   g_return_if_fail (pivot_point->y == -1.f || | ||||
|                     (pivot_point->y >= 0.f && pivot_point->y <= 1.f)); | ||||
|  | ||||
|   if (graphene_point_equal (&align->pivot, pivot_point)) | ||||
|     return; | ||||
|  | ||||
|   align->pivot = *pivot_point; | ||||
|  | ||||
|   if (align->actor != NULL) | ||||
|     clutter_actor_queue_relayout (align->actor); | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_PIVOT_POINT]); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_align_constraint_get_pivot_point | ||||
|  * @align: a #ClutterAlignConstraint | ||||
|  * @pivot_point: (out caller-allocates): return location for a #GraphenePoint | ||||
|  * | ||||
|  * Gets the pivot point used by the constraint set with | ||||
|  * clutter_align_constraint_set_pivot_point(). If no custom pivot | ||||
|  * point is set, -1 is set. | ||||
|  */ | ||||
| void | ||||
| clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align, | ||||
|                                           graphene_point_t       *pivot_point) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align)); | ||||
|   g_return_if_fail (pivot_point != NULL); | ||||
|  | ||||
|   *pivot_point = align->pivot; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_align_constraint_set_factor: | ||||
|  * @align: a #ClutterAlignConstraint | ||||
|   | ||||
| @@ -67,12 +67,6 @@ void               clutter_align_constraint_set_align_axis (ClutterAlignConstrai | ||||
| CLUTTER_EXPORT | ||||
| ClutterAlignAxis   clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align); | ||||
| CLUTTER_EXPORT | ||||
| void               clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align, | ||||
|                                                              const graphene_point_t *pivot_point); | ||||
| CLUTTER_EXPORT | ||||
| void               clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align, | ||||
|                                                              graphene_point_t       *pivot_point); | ||||
| CLUTTER_EXPORT | ||||
| void               clutter_align_constraint_set_factor     (ClutterAlignConstraint *align, | ||||
|                                                             gfloat                  factor); | ||||
| CLUTTER_EXPORT | ||||
|   | ||||
| @@ -194,25 +194,3 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable, | ||||
|   else | ||||
|     return clutter_interval_compute_value (interval, progress, value); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_animatable_get_actor: | ||||
|  * @animatable: a #ClutterAnimatable | ||||
|  * | ||||
|  * Get animated actor. | ||||
|  * | ||||
|  * Return value: (transfer none): a #ClutterActor | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_animatable_get_actor (ClutterAnimatable *animatable) | ||||
| { | ||||
|   ClutterAnimatableInterface *iface; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL); | ||||
|  | ||||
|   iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); | ||||
|  | ||||
|   g_return_val_if_fail (iface->get_actor, NULL); | ||||
|  | ||||
|   return iface->get_actor (animatable); | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,6 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable, | ||||
|  *   animatable property | ||||
|  * @interpolate_value: virtual function for interpolating the progress | ||||
|  *   of a property | ||||
|  * @get_actor: virtual function for getting associated actor | ||||
|  * | ||||
|  * Since: 1.0 | ||||
|  */ | ||||
| @@ -73,7 +72,6 @@ struct _ClutterAnimatableInterface | ||||
|                                      ClutterInterval   *interval, | ||||
|                                      gdouble            progress, | ||||
|                                      GValue            *value); | ||||
|   ClutterActor * (* get_actor)      (ClutterAnimatable *animatable); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| @@ -94,9 +92,6 @@ gboolean    clutter_animatable_interpolate_value (ClutterAnimatable *animatable, | ||||
|                                                   gdouble            progress, | ||||
|                                                   GValue            *value); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor * clutter_animatable_get_actor      (ClutterAnimatable *animatable); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_ANIMATABLE_H__ */ | ||||
|   | ||||
| @@ -53,8 +53,6 @@ struct _ClutterBackend | ||||
|   gfloat units_per_em; | ||||
|   gint32 units_serial; | ||||
|  | ||||
|   float fallback_resource_scale; | ||||
|  | ||||
|   ClutterStageWindow *stage_window; | ||||
|  | ||||
|   ClutterInputMethod *input_method; | ||||
| @@ -136,12 +134,6 @@ void                    clutter_set_allowed_drivers                     (const c | ||||
| CLUTTER_EXPORT | ||||
| ClutterStageWindow *    clutter_backend_get_stage_window                (ClutterBackend         *backend); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend, | ||||
|                                                   float           fallback_resource_scale); | ||||
|  | ||||
| float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_BACKEND_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -601,8 +601,6 @@ clutter_backend_init (ClutterBackend *self) | ||||
|   self->units_serial = 1; | ||||
|  | ||||
|   self->dummy_onscreen = NULL; | ||||
|  | ||||
|   self->fallback_resource_scale = 1.f; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1033,16 +1031,3 @@ clutter_backend_get_default_seat (ClutterBackend *backend) | ||||
|  | ||||
|   return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend); | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_backend_set_fallback_resource_scale (ClutterBackend *backend, | ||||
|                                              float           fallback_resource_scale) | ||||
| { | ||||
|   backend->fallback_resource_scale = fallback_resource_scale; | ||||
| } | ||||
|  | ||||
| float | ||||
| clutter_backend_get_fallback_resource_scale (ClutterBackend *backend) | ||||
| { | ||||
|   return backend->fallback_resource_scale; | ||||
| } | ||||
|   | ||||
| @@ -38,14 +38,12 @@ | ||||
|  * | ||||
|  * |[<!-- language="C" --> | ||||
|  * // source | ||||
|  * rect[0] = clutter_actor_new (); | ||||
|  * clutter_actor_set_background_color (rect[0], &red_color); | ||||
|  * rect[0] = clutter_rectangle_new_with_color (&red_color); | ||||
|  * clutter_actor_set_position (rect[0], x_pos, y_pos); | ||||
|  * clutter_actor_set_size (rect[0], 100, 100); | ||||
|  * | ||||
|  * // second rectangle | ||||
|  * rect[1] = clutter_actor_new (); | ||||
|  * clutter_actor_set_background_color (rect[1], &green_color); | ||||
|  * rect[1] = clutter_rectangle_new_with_color (&green_color); | ||||
|  * clutter_actor_set_size (rect[1], 100, 100); | ||||
|  * clutter_actor_set_opacity (rect[1], 0); | ||||
|  * | ||||
| @@ -55,8 +53,7 @@ | ||||
|  * clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint); | ||||
|  * | ||||
|  * // third rectangle | ||||
|  * rect[2] = clutter_actor_new (); | ||||
|  * clutter_actor_set_background_color (rect[2], &blue_color); | ||||
|  * rect[2] = clutter_rectangle_new_with_color (&blue_color); | ||||
|  * clutter_actor_set_size (rect[2], 100, 100); | ||||
|  * clutter_actor_set_opacity (rect[2], 0); | ||||
|  * | ||||
| @@ -168,9 +165,6 @@ clutter_bind_constraint_update_preferred_size (ClutterConstraint  *constraint, | ||||
|         bind->coordinate == CLUTTER_BIND_ALL)) | ||||
|     return; | ||||
|  | ||||
|   if (clutter_actor_contains (bind->source, actor)) | ||||
|     return; | ||||
|  | ||||
|   switch (direction) | ||||
|     { | ||||
|     case CLUTTER_ORIENTATION_HORIZONTAL: | ||||
|   | ||||
| @@ -81,6 +81,9 @@ struct _ClutterBlurEffect | ||||
|  | ||||
|   gint pixel_step_uniform; | ||||
|  | ||||
|   gint tex_width; | ||||
|   gint tex_height; | ||||
|  | ||||
|   CoglPipeline *pipeline; | ||||
| }; | ||||
|  | ||||
| @@ -95,42 +98,20 @@ G_DEFINE_TYPE (ClutterBlurEffect, | ||||
|                clutter_blur_effect, | ||||
|                CLUTTER_TYPE_OFFSCREEN_EFFECT); | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect, | ||||
|                                      CoglTexture            *texture) | ||||
| { | ||||
|   ClutterBlurEffect *blur_effect = CLUTTER_BLUR_EFFECT (effect); | ||||
|  | ||||
|   if (blur_effect->pixel_step_uniform > -1) | ||||
|     { | ||||
|       float pixel_step[2]; | ||||
|       int tex_width, tex_height; | ||||
|  | ||||
|       tex_width = cogl_texture_get_width (texture); | ||||
|       tex_height = cogl_texture_get_height (texture); | ||||
|  | ||||
|       pixel_step[0] = 1.0f / tex_width; | ||||
|       pixel_step[1] = 1.0f / tex_height; | ||||
|  | ||||
|       cogl_pipeline_set_uniform_float (blur_effect->pipeline, | ||||
|                                        blur_effect->pixel_step_uniform, | ||||
|                                        2, /* n_components */ | ||||
|                                        1, /* count */ | ||||
|                                        pixel_step); | ||||
|     } | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (blur_effect->pipeline, 0, texture); | ||||
|  | ||||
|   return cogl_object_ref (blur_effect->pipeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_blur_effect_pre_paint (ClutterEffect       *effect, | ||||
|                                ClutterPaintNode    *node, | ||||
|                                ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect); | ||||
|   ClutterEffectClass *parent_class; | ||||
|  | ||||
|   if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) | ||||
|     return FALSE; | ||||
|  | ||||
|   self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); | ||||
|   if (self->actor == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) | ||||
|     { | ||||
|       /* if we don't have support for GLSL shaders then we | ||||
| @@ -144,7 +125,59 @@ clutter_blur_effect_pre_paint (ClutterEffect       *effect, | ||||
|     } | ||||
|  | ||||
|   parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class); | ||||
|   return parent_class->pre_paint (effect, node, paint_context); | ||||
|   if (parent_class->pre_paint (effect, paint_context)) | ||||
|     { | ||||
|       ClutterOffscreenEffect *offscreen_effect = | ||||
|         CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|       CoglHandle texture; | ||||
|  | ||||
|       texture = clutter_offscreen_effect_get_texture (offscreen_effect); | ||||
|       self->tex_width = cogl_texture_get_width (texture); | ||||
|       self->tex_height = cogl_texture_get_height (texture); | ||||
|  | ||||
|       if (self->pixel_step_uniform > -1) | ||||
|         { | ||||
|           gfloat pixel_step[2]; | ||||
|  | ||||
|           pixel_step[0] = 1.0f / self->tex_width; | ||||
|           pixel_step[1] = 1.0f / self->tex_height; | ||||
|  | ||||
|           cogl_pipeline_set_uniform_float (self->pipeline, | ||||
|                                            self->pixel_step_uniform, | ||||
|                                            2, /* n_components */ | ||||
|                                            1, /* count */ | ||||
|                                            pixel_step); | ||||
|         } | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                   ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect); | ||||
|   CoglFramebuffer *framebuffer = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|   guint8 paint_opacity; | ||||
|  | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (self->actor); | ||||
|  | ||||
|   cogl_pipeline_set_color4ub (self->pipeline, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity); | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                    self->pipeline, | ||||
|                                    0, 0, | ||||
|                                    self->tex_width, self->tex_height); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -196,7 +229,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass) | ||||
|   effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume; | ||||
|  | ||||
|   offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); | ||||
|   offscreen_class->create_pipeline = clutter_blur_effect_create_pipeline; | ||||
|   offscreen_class->paint_target = clutter_blur_effect_paint_target; | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -167,10 +167,8 @@ get_preferred_size_for_orientation (ClutterBoxLayout   *self, | ||||
|   ClutterActor *child; | ||||
|   gint n_children = 0; | ||||
|   gfloat minimum, natural; | ||||
|   float largest_min_size, largest_nat_size; | ||||
|  | ||||
|   minimum = natural = 0; | ||||
|   largest_min_size = largest_nat_size = 0; | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, container); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
| @@ -185,22 +183,8 @@ get_preferred_size_for_orientation (ClutterBoxLayout   *self, | ||||
|       get_child_size (child, priv->orientation, | ||||
| 		      for_size, &child_min, &child_nat); | ||||
|  | ||||
|       if (priv->is_homogeneous) | ||||
|         { | ||||
|           largest_min_size = MAX (largest_min_size, child_min); | ||||
|           largest_nat_size = MAX (largest_nat_size, child_nat); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           minimum += child_min; | ||||
|           natural += child_nat; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if (priv->is_homogeneous) | ||||
|     { | ||||
|       minimum = largest_min_size * n_children; | ||||
|       natural = largest_nat_size * n_children; | ||||
|       minimum += child_min; | ||||
|       natural += child_nat; | ||||
|     } | ||||
|  | ||||
|   if (n_children > 1) | ||||
| @@ -331,8 +315,6 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout   *self, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       size -= (nvis_children - 1) * priv->spacing; | ||||
|  | ||||
|       /* Bring children up to size first */ | ||||
|       if (isnormal (size) || size == 0) | ||||
|         { | ||||
|   | ||||
| @@ -69,6 +69,9 @@ struct _ClutterBrightnessContrastEffect | ||||
|   gint brightness_offset_uniform; | ||||
|   gint contrast_uniform; | ||||
|  | ||||
|   gint tex_width; | ||||
|   gint tex_height; | ||||
|  | ||||
|   CoglPipeline *pipeline; | ||||
| }; | ||||
|  | ||||
| @@ -126,26 +129,16 @@ will_have_no_effect (ClutterBrightnessContrastEffect *self) | ||||
|           G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON)); | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effect, | ||||
|                                                     CoglTexture            *texture) | ||||
| { | ||||
|   ClutterBrightnessContrastEffect *self = | ||||
|     CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|   return cogl_object_ref (self->pipeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_brightness_contrast_effect_pre_paint (ClutterEffect       *effect, | ||||
|                                               ClutterPaintNode    *node, | ||||
|                                               ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); | ||||
|   ClutterEffectClass *parent_class; | ||||
|  | ||||
|   if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (will_have_no_effect (self)) | ||||
|     return FALSE; | ||||
|  | ||||
| @@ -164,8 +157,47 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect       *effect, | ||||
|  | ||||
|   parent_class = | ||||
|     CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class); | ||||
|   if (parent_class->pre_paint (effect, paint_context)) | ||||
|     { | ||||
|       ClutterOffscreenEffect *offscreen_effect = | ||||
|         CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|       CoglHandle texture; | ||||
|  | ||||
|   return parent_class->pre_paint (effect, node, paint_context); | ||||
|       texture = clutter_offscreen_effect_get_texture (offscreen_effect); | ||||
|       self->tex_width = cogl_texture_get_width (texture); | ||||
|       self->tex_height = cogl_texture_get_height (texture); | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                                  ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); | ||||
|   CoglFramebuffer *framebuffer = | ||||
|    clutter_paint_context_get_framebuffer (paint_context); | ||||
|   ClutterActor *actor; | ||||
|   guint8 paint_opacity; | ||||
|  | ||||
|   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|  | ||||
|   cogl_pipeline_set_color4ub (self->pipeline, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity); | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                    self->pipeline, | ||||
|                                    0, 0, | ||||
|                                    self->tex_width, self->tex_height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -265,7 +297,7 @@ clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectCl | ||||
|   ClutterOffscreenEffectClass *offscreen_class; | ||||
|  | ||||
|   offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); | ||||
|   offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline; | ||||
|   offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target; | ||||
|  | ||||
|   effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint; | ||||
|  | ||||
|   | ||||
| @@ -52,8 +52,6 @@ | ||||
| struct _ClutterClonePrivate | ||||
| { | ||||
|   ClutterActor *clone_source; | ||||
|   float x_scale, y_scale; | ||||
|  | ||||
|   gulong source_destroy_id; | ||||
| }; | ||||
|  | ||||
| @@ -124,6 +122,8 @@ static void | ||||
| clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix) | ||||
| { | ||||
|   ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; | ||||
|   ClutterActorBox box, source_box; | ||||
|   gfloat x_scale, y_scale; | ||||
|  | ||||
|   /* First chain up and apply all the standard ClutterActor | ||||
|    * transformations... */ | ||||
| @@ -134,7 +134,21 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix) | ||||
|   if (priv->clone_source == NULL) | ||||
|     return; | ||||
|  | ||||
|   cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f); | ||||
|   /* get our allocated size */ | ||||
|   clutter_actor_get_allocation_box (self, &box); | ||||
|  | ||||
|   /* and get the allocated size of the source */ | ||||
|   clutter_actor_get_allocation_box (priv->clone_source, &source_box); | ||||
|  | ||||
|   /* We need to scale what the clone-source actor paints to fill our own | ||||
|    * allocation... | ||||
|    */ | ||||
|   x_scale = clutter_actor_box_get_width (&box) | ||||
|           / clutter_actor_box_get_width (&source_box); | ||||
|   y_scale = clutter_actor_box_get_height (&box) | ||||
|           / clutter_actor_box_get_height (&source_box); | ||||
|  | ||||
|   cogl_matrix_scale (matrix, x_scale, y_scale, x_scale); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -230,8 +244,6 @@ clutter_clone_allocate (ClutterActor           *self, | ||||
| { | ||||
|   ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; | ||||
|   ClutterActorClass *parent_class; | ||||
|   ClutterActorBox source_box; | ||||
|   float x_scale, y_scale; | ||||
|  | ||||
|   /* chain up */ | ||||
|   parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class); | ||||
| @@ -247,24 +259,6 @@ clutter_clone_allocate (ClutterActor           *self, | ||||
|       !clutter_actor_has_allocation (priv->clone_source)) | ||||
|     clutter_actor_allocate_preferred_size (priv->clone_source); | ||||
|  | ||||
|   clutter_actor_get_allocation_box (priv->clone_source, &source_box); | ||||
|  | ||||
|   /* We need to scale what the clone-source actor paints to fill our own | ||||
|    * allocation... | ||||
|    */ | ||||
|   x_scale = clutter_actor_box_get_width (box) | ||||
|           / clutter_actor_box_get_width (&source_box); | ||||
|   y_scale = clutter_actor_box_get_height (box) | ||||
|           / clutter_actor_box_get_height (&source_box); | ||||
|  | ||||
|   if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) || | ||||
|       !G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON)) | ||||
|     { | ||||
|       priv->x_scale = x_scale; | ||||
|       priv->y_scale = y_scale; | ||||
|       clutter_actor_invalidate_transform (CLUTTER_ACTOR (self)); | ||||
|     } | ||||
|  | ||||
| #if 0 | ||||
|   /* XXX - this is wrong: ClutterClone cannot clone unparented | ||||
|    * actors, as it will break all invariants | ||||
| @@ -370,9 +364,6 @@ static void | ||||
| clutter_clone_init (ClutterClone *self) | ||||
| { | ||||
|   self->priv = clutter_clone_get_instance_private (self); | ||||
|  | ||||
|   self->priv->x_scale = 1.f; | ||||
|   self->priv->y_scale = 1.f; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -59,6 +59,9 @@ struct _ClutterColorizeEffect | ||||
|  | ||||
|   gint tint_uniform; | ||||
|  | ||||
|   gint tex_width; | ||||
|   gint tex_height; | ||||
|  | ||||
|   CoglPipeline *pipeline; | ||||
| }; | ||||
|  | ||||
| @@ -101,24 +104,16 @@ G_DEFINE_TYPE (ClutterColorizeEffect, | ||||
|                clutter_colorize_effect, | ||||
|                CLUTTER_TYPE_OFFSCREEN_EFFECT); | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect, | ||||
|                                          CoglTexture            *texture) | ||||
| { | ||||
|   ClutterColorizeEffect *colorize_effect = CLUTTER_COLORIZE_EFFECT (effect); | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (colorize_effect->pipeline, 0, texture); | ||||
|  | ||||
|   return cogl_object_ref (colorize_effect->pipeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_colorize_effect_pre_paint (ClutterEffect       *effect, | ||||
|                                    ClutterPaintNode    *node, | ||||
|                                    ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); | ||||
|   ClutterEffectClass *parent_class; | ||||
|  | ||||
|   if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) | ||||
|     { | ||||
|       /* if we don't have support for GLSL shaders then we | ||||
| @@ -132,7 +127,47 @@ clutter_colorize_effect_pre_paint (ClutterEffect       *effect, | ||||
|     } | ||||
|  | ||||
|   parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); | ||||
|   return parent_class->pre_paint (effect, node, paint_context); | ||||
|   if (parent_class->pre_paint (effect, paint_context)) | ||||
|     { | ||||
|       ClutterOffscreenEffect *offscreen_effect = | ||||
|         CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|       CoglHandle texture; | ||||
|  | ||||
|       texture = clutter_offscreen_effect_get_texture (offscreen_effect); | ||||
|       self->tex_width = cogl_texture_get_width (texture); | ||||
|       self->tex_height = cogl_texture_get_height (texture); | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                       ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); | ||||
|   CoglFramebuffer *framebuffer = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|   ClutterActor *actor; | ||||
|   guint8 paint_opacity; | ||||
|  | ||||
|   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|  | ||||
|   cogl_pipeline_set_color4ub (self->pipeline, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity); | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                    self->pipeline, | ||||
|                                    0, 0, | ||||
|                                    self->tex_width, self->tex_height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -198,7 +233,7 @@ clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass) | ||||
|   ClutterOffscreenEffectClass *offscreen_class; | ||||
|  | ||||
|   offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); | ||||
|   offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline; | ||||
|   offscreen_class->paint_target = clutter_colorize_effect_paint_target; | ||||
|  | ||||
|   effect_class->pre_paint = clutter_colorize_effect_pre_paint; | ||||
|  | ||||
|   | ||||
| @@ -58,12 +58,9 @@ | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| #include "clutter-color.h" | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-offscreen-effect-private.h" | ||||
| #include "clutter-paint-node.h" | ||||
| #include "clutter-paint-nodes.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| #define DEFAULT_N_TILES         32 | ||||
| @@ -169,16 +166,19 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta, | ||||
|  | ||||
| static void | ||||
| clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                     ClutterPaintNode       *node, | ||||
|                                     ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); | ||||
|   ClutterDeformEffectPrivate *priv = self->priv; | ||||
|   CoglHandle material; | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglDepthState depth_state; | ||||
|   CoglFramebuffer *fb = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|  | ||||
|   if (priv->is_dirty) | ||||
|     { | ||||
|       graphene_rect_t rect; | ||||
|       gboolean mapped_buffer; | ||||
|       CoglVertexP3T2C4 *verts; | ||||
|       ClutterActor *actor; | ||||
| @@ -192,7 +192,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|       /* if we don't have a target size, fall back to the actor's | ||||
|        * allocation, though wrong it might be | ||||
|        */ | ||||
|       if (!clutter_offscreen_effect_get_target_size (effect, &width, &height)) | ||||
|       if (clutter_offscreen_effect_get_target_rect (effect, &rect)) | ||||
|         { | ||||
|           width = graphene_rect_get_width (&rect); | ||||
|           height = graphene_rect_get_height (&rect); | ||||
|         } | ||||
|       else | ||||
|         clutter_actor_get_size (actor, &width, &height); | ||||
|  | ||||
|       /* XXX ideally, the sub-classes should tell us what they | ||||
| @@ -272,7 +277,8 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|       priv->is_dirty = FALSE; | ||||
|     } | ||||
|  | ||||
|   pipeline = clutter_offscreen_effect_get_pipeline (effect); | ||||
|   material = clutter_offscreen_effect_get_target (effect); | ||||
|   pipeline = COGL_PIPELINE (material); | ||||
|  | ||||
|   /* enable depth testing */ | ||||
|   cogl_depth_state_init (&depth_state); | ||||
| @@ -286,22 +292,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                       COGL_PIPELINE_CULL_FACE_MODE_BACK); | ||||
|  | ||||
|   /* draw the front */ | ||||
|   if (pipeline != NULL) | ||||
|     { | ||||
|       ClutterPaintNode *front_node; | ||||
|  | ||||
|       front_node = clutter_pipeline_node_new (pipeline); | ||||
|       clutter_paint_node_set_static_name (front_node, | ||||
|                                           "ClutterDeformEffect (front)"); | ||||
|       clutter_paint_node_add_child (node, front_node); | ||||
|       clutter_paint_node_add_primitive (front_node, priv->primitive); | ||||
|       clutter_paint_node_unref (front_node); | ||||
|     } | ||||
|   if (material != NULL) | ||||
|     cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive); | ||||
|  | ||||
|   /* draw the back */ | ||||
|   if (priv->back_pipeline != NULL) | ||||
|     { | ||||
|       ClutterPaintNode *back_node; | ||||
|       CoglPipeline *back_pipeline; | ||||
|  | ||||
|       /* We probably shouldn't be modifying the user's material so | ||||
| @@ -311,30 +307,20 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|       cogl_pipeline_set_cull_face_mode (back_pipeline, | ||||
|                                         COGL_PIPELINE_CULL_FACE_MODE_FRONT); | ||||
|  | ||||
|       cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive); | ||||
|  | ||||
|       back_node = clutter_pipeline_node_new (back_pipeline); | ||||
|       clutter_paint_node_set_static_name (back_node, | ||||
|                                           "ClutterDeformEffect (back)"); | ||||
|       clutter_paint_node_add_child (node, back_node); | ||||
|       clutter_paint_node_add_primitive (back_node, priv->primitive); | ||||
|  | ||||
|       clutter_paint_node_unref (back_node); | ||||
|       cogl_object_unref (back_pipeline); | ||||
|     } | ||||
|  | ||||
|   if (G_UNLIKELY (priv->lines_primitive != NULL)) | ||||
|     { | ||||
|       const ClutterColor *red; | ||||
|       ClutterPaintNode *lines_node; | ||||
|  | ||||
|       red = clutter_color_get_static (CLUTTER_COLOR_RED); | ||||
|  | ||||
|       lines_node = clutter_color_node_new (red); | ||||
|       clutter_paint_node_set_static_name (lines_node, | ||||
|                                           "ClutterDeformEffect (lines)"); | ||||
|       clutter_paint_node_add_child (node, lines_node); | ||||
|       clutter_paint_node_add_primitive (lines_node, priv->lines_primitive); | ||||
|       clutter_paint_node_unref (lines_node); | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0); | ||||
|       cogl_framebuffer_draw_primitive (fb, lines_pipeline, | ||||
|                                        priv->lines_primitive); | ||||
|       cogl_object_unref (lines_pipeline); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,13 @@ | ||||
|  | ||||
| #define __CLUTTER_DEPRECATED_H_INSIDE__ | ||||
|  | ||||
| #include "deprecated/clutter-actor.h" | ||||
| #include "deprecated/clutter-box.h" | ||||
| #include "deprecated/clutter-container.h" | ||||
| #include "deprecated/clutter-group.h" | ||||
| #include "deprecated/clutter-rectangle.h" | ||||
| #include "deprecated/clutter-stage.h" | ||||
| #include "deprecated/clutter-timeline.h" | ||||
|  | ||||
| #undef __CLUTTER_DEPRECATED_H_INSIDE__ | ||||
|  | ||||
|   | ||||
| @@ -111,25 +111,16 @@ G_DEFINE_TYPE (ClutterDesaturateEffect, | ||||
|                clutter_desaturate_effect, | ||||
|                CLUTTER_TYPE_OFFSCREEN_EFFECT); | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect, | ||||
|                                            CoglTexture            *texture) | ||||
| { | ||||
|   ClutterDesaturateEffect *desaturate_effect = | ||||
|     CLUTTER_DESATURATE_EFFECT (effect); | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (desaturate_effect->pipeline, 0, texture); | ||||
|  | ||||
|   return cogl_object_ref (desaturate_effect->pipeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_desaturate_effect_pre_paint (ClutterEffect       *effect, | ||||
|                                      ClutterPaintNode    *node, | ||||
|                                      ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect); | ||||
|   ClutterEffectClass *parent_class; | ||||
|  | ||||
|   if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) | ||||
|     { | ||||
|       /* if we don't have support for GLSL shaders then we | ||||
| @@ -143,7 +134,52 @@ clutter_desaturate_effect_pre_paint (ClutterEffect       *effect, | ||||
|     } | ||||
|  | ||||
|   parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class); | ||||
|   return parent_class->pre_paint (effect, node, paint_context); | ||||
|   if (parent_class->pre_paint (effect, paint_context)) | ||||
|     { | ||||
|       ClutterOffscreenEffect *offscreen_effect = | ||||
|         CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|       CoglHandle texture; | ||||
|  | ||||
|       texture = clutter_offscreen_effect_get_texture (offscreen_effect); | ||||
|       self->tex_width = cogl_texture_get_width (texture); | ||||
|       self->tex_height = cogl_texture_get_height (texture); | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                         ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect); | ||||
|   CoglFramebuffer *framebuffer = | ||||
|    clutter_paint_context_get_framebuffer (paint_context); | ||||
|   ClutterActor *actor; | ||||
|   CoglHandle texture; | ||||
|   guint8 paint_opacity; | ||||
|  | ||||
|   texture = clutter_offscreen_effect_get_texture (effect); | ||||
|   cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); | ||||
|  | ||||
|   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (actor); | ||||
|  | ||||
|   cogl_pipeline_set_color4ub (self->pipeline, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity); | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                    self->pipeline, | ||||
|                                    0, 0, | ||||
|                                    cogl_texture_get_width (texture), | ||||
|                                    cogl_texture_get_height (texture)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -218,7 +254,7 @@ clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass) | ||||
|   ClutterOffscreenEffectClass *offscreen_class; | ||||
|  | ||||
|   offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); | ||||
|   offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline; | ||||
|   offscreen_class->paint_target = clutter_desaturate_effect_paint_target; | ||||
|  | ||||
|   effect_class->pre_paint = clutter_desaturate_effect_pre_paint; | ||||
|  | ||||
|   | ||||
| @@ -5,11 +5,14 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| gboolean        _clutter_effect_pre_paint               (ClutterEffect           *effect, | ||||
|                                                          ClutterPaintContext     *paint_context); | ||||
| void            _clutter_effect_post_paint              (ClutterEffect           *effect, | ||||
|                                                          ClutterPaintContext     *paint_context); | ||||
| gboolean        _clutter_effect_modify_paint_volume     (ClutterEffect           *effect, | ||||
|                                                          ClutterPaintVolume      *volume); | ||||
| gboolean        _clutter_effect_has_custom_paint_volume (ClutterEffect           *effect); | ||||
| void            _clutter_effect_paint                   (ClutterEffect           *effect, | ||||
|                                                          ClutterPaintNode        *node, | ||||
|                                                          ClutterPaintContext     *paint_context, | ||||
|                                                          ClutterEffectPaintFlags  flags); | ||||
| void            _clutter_effect_pick                    (ClutterEffect           *effect, | ||||
|   | ||||
| @@ -169,8 +169,6 @@ | ||||
| #include "clutter-effect-private.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-paint-node-private.h" | ||||
| #include "clutter-paint-nodes.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-actor-private.h" | ||||
|  | ||||
| @@ -180,7 +178,6 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect, | ||||
|  | ||||
| static gboolean | ||||
| clutter_effect_real_pre_paint (ClutterEffect       *effect, | ||||
|                                ClutterPaintNode    *node, | ||||
|                                ClutterPaintContext *paint_context) | ||||
| { | ||||
|   return TRUE; | ||||
| @@ -188,7 +185,6 @@ clutter_effect_real_pre_paint (ClutterEffect       *effect, | ||||
|  | ||||
| static void | ||||
| clutter_effect_real_post_paint (ClutterEffect       *effect, | ||||
|                                 ClutterPaintNode    *node, | ||||
|                                 ClutterPaintContext *paint_context) | ||||
| { | ||||
| } | ||||
| @@ -200,41 +196,26 @@ clutter_effect_real_modify_paint_volume (ClutterEffect      *effect, | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_real_paint_node (ClutterEffect           *effect, | ||||
|                                 ClutterPaintNode        *node, | ||||
|                                 ClutterPaintContext     *paint_context, | ||||
|                                 ClutterEffectPaintFlags  flags) | ||||
| { | ||||
|   ClutterPaintNode *actor_node; | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); | ||||
|  | ||||
|   actor_node = clutter_actor_node_new (actor, -1); | ||||
|   clutter_paint_node_add_child (node, actor_node); | ||||
|   clutter_paint_node_unref (actor_node); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_real_paint (ClutterEffect           *effect, | ||||
|                            ClutterPaintNode        *node, | ||||
|                            ClutterPaintContext     *paint_context, | ||||
|                            ClutterEffectPaintFlags  flags) | ||||
| { | ||||
|   ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect); | ||||
|   ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect); | ||||
|   ClutterActor *actor; | ||||
|   gboolean pre_paint_succeeded; | ||||
|  | ||||
|   /* The default implementation provides a compatibility wrapper for | ||||
|      effects that haven't migrated to use the 'paint' virtual yet. This | ||||
|      just calls the old pre and post virtuals before chaining on */ | ||||
|  | ||||
|   pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context); | ||||
|   pre_paint_succeeded = _clutter_effect_pre_paint (effect, paint_context); | ||||
|  | ||||
|   effect_class->paint_node (effect, node, paint_context, flags); | ||||
|   actor = clutter_actor_meta_get_actor (actor_meta); | ||||
|   clutter_actor_continue_paint (actor, paint_context); | ||||
|  | ||||
|   if (pre_paint_succeeded) | ||||
|     effect_class->post_paint (effect, node, paint_context); | ||||
|     _clutter_effect_post_paint (effect, paint_context); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -274,7 +255,6 @@ clutter_effect_class_init (ClutterEffectClass *klass) | ||||
|   klass->post_paint = clutter_effect_real_post_paint; | ||||
|   klass->modify_paint_volume = clutter_effect_real_modify_paint_volume; | ||||
|   klass->paint = clutter_effect_real_paint; | ||||
|   klass->paint_node = clutter_effect_real_paint_node; | ||||
|   klass->pick = clutter_effect_real_pick; | ||||
| } | ||||
|  | ||||
| @@ -283,18 +263,32 @@ clutter_effect_init (ClutterEffect *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_effect_pre_paint (ClutterEffect       *effect, | ||||
|                            ClutterPaintContext *paint_context) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE); | ||||
|  | ||||
|   return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect, paint_context); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_effect_post_paint (ClutterEffect       *effect, | ||||
|                             ClutterPaintContext *paint_context) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_EFFECT (effect)); | ||||
|  | ||||
|   CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect, paint_context); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_effect_paint (ClutterEffect           *effect, | ||||
|                        ClutterPaintNode        *node, | ||||
|                        ClutterPaintContext     *paint_context, | ||||
|                        ClutterEffectPaintFlags  flags) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_EFFECT (effect)); | ||||
|  | ||||
|   CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, | ||||
|                                             node, | ||||
|                                             paint_context, | ||||
|                                             flags); | ||||
|   CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, paint_context, flags); | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
| @@ -77,21 +77,14 @@ struct _ClutterEffectClass | ||||
|  | ||||
|   /*< public >*/ | ||||
|   gboolean (* pre_paint)           (ClutterEffect           *effect, | ||||
|                                     ClutterPaintNode        *node, | ||||
|                                     ClutterPaintContext     *paint_context); | ||||
|   void     (* post_paint)          (ClutterEffect           *effect, | ||||
|                                     ClutterPaintNode        *node, | ||||
|                                     ClutterPaintContext     *paint_context); | ||||
|  | ||||
|   gboolean (* modify_paint_volume) (ClutterEffect           *effect, | ||||
|                                     ClutterPaintVolume      *volume); | ||||
|  | ||||
|   void     (* paint)               (ClutterEffect           *effect, | ||||
|                                     ClutterPaintNode        *node, | ||||
|                                     ClutterPaintContext     *paint_context, | ||||
|                                     ClutterEffectPaintFlags  flags); | ||||
|   void     (* paint_node)          (ClutterEffect           *effect, | ||||
|                                     ClutterPaintNode        *node, | ||||
|                                     ClutterPaintContext     *paint_context, | ||||
|                                     ClutterEffectPaintFlags  flags); | ||||
|   void     (* pick)                (ClutterEffect           *effect, | ||||
|   | ||||
| @@ -1317,6 +1317,8 @@ typedef enum | ||||
|  *   painting the stages | ||||
|  * @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after | ||||
|  *   painting the stages | ||||
|  * @CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD: Ensure that a new frame | ||||
|  *   is queued after adding the repaint function | ||||
|  * | ||||
|  * Flags to pass to clutter_threads_add_repaint_func_full(). | ||||
|  * | ||||
| @@ -1326,6 +1328,7 @@ typedef enum | ||||
| { | ||||
|   CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0, | ||||
|   CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1, | ||||
|   CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2 | ||||
| } ClutterRepaintFlags; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,550 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat Inc. | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter/clutter-frame-clock.h" | ||||
|  | ||||
| #include "clutter/clutter-main.h" | ||||
| #include "clutter/clutter-private.h" | ||||
| #include "clutter/clutter-timeline-private.h" | ||||
| #include "cogl/cogl-trace.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   DESTROY, | ||||
|  | ||||
|   N_SIGNALS | ||||
| }; | ||||
|  | ||||
| static guint signals[N_SIGNALS]; | ||||
|  | ||||
| /* Wait 2ms after vblank before starting to draw next frame */ | ||||
| #define SYNC_DELAY_US ms2us (2) | ||||
|  | ||||
| typedef struct _ClutterFrameListener | ||||
| { | ||||
|   const ClutterFrameListenerIface *iface; | ||||
|   gpointer user_data; | ||||
| } ClutterFrameListener; | ||||
|  | ||||
| typedef struct _ClutterClockSource | ||||
| { | ||||
|   GSource source; | ||||
|  | ||||
|   ClutterFrameClock *frame_clock; | ||||
| } ClutterClockSource; | ||||
|  | ||||
| typedef enum _ClutterFrameClockState | ||||
| { | ||||
|   CLUTTER_FRAME_CLOCK_STATE_INIT, | ||||
|   CLUTTER_FRAME_CLOCK_STATE_IDLE, | ||||
|   CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, | ||||
|   CLUTTER_FRAME_CLOCK_STATE_DISPATCHING, | ||||
|   CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED, | ||||
| } ClutterFrameClockState; | ||||
|  | ||||
| struct _ClutterFrameClock | ||||
| { | ||||
|   GObject parent; | ||||
|  | ||||
|   float refresh_rate; | ||||
|   ClutterFrameListener listener; | ||||
|  | ||||
|   GSource *source; | ||||
|  | ||||
|   int64_t frame_count; | ||||
|  | ||||
|   ClutterFrameClockState state; | ||||
|   int64_t last_presentation_time_us; | ||||
|  | ||||
|   gboolean is_next_presentation_time_valid; | ||||
|   int64_t next_presentation_time_us; | ||||
|  | ||||
|   gboolean pending_reschedule; | ||||
|   gboolean pending_reschedule_now; | ||||
|  | ||||
|   int inhibit_count; | ||||
|  | ||||
|   GList *timelines; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock, | ||||
|                G_TYPE_OBJECT) | ||||
|  | ||||
| float | ||||
| clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   return frame_clock->refresh_rate; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock, | ||||
|                                   ClutterTimeline   *timeline) | ||||
| { | ||||
|   gboolean is_first; | ||||
|  | ||||
|   if (g_list_find (frame_clock->timelines, timeline)) | ||||
|     return; | ||||
|  | ||||
|   is_first = !frame_clock->timelines; | ||||
|  | ||||
|   frame_clock->timelines = g_list_prepend (frame_clock->timelines, timeline); | ||||
|  | ||||
|   if (is_first) | ||||
|     clutter_frame_clock_schedule_update (frame_clock); | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock, | ||||
|                                      ClutterTimeline   *timeline) | ||||
| { | ||||
|   frame_clock->timelines = g_list_remove (frame_clock->timelines, timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| advance_timelines (ClutterFrameClock *frame_clock, | ||||
|                    int64_t            time_us) | ||||
| { | ||||
|   GList *timelines; | ||||
|   GList *l; | ||||
|  | ||||
|   /* we protect ourselves from timelines being removed during | ||||
|    * the advancement by other timelines by copying the list of | ||||
|    * timelines, taking a reference on them, iterating over the | ||||
|    * copied list and then releasing the reference. | ||||
|    * | ||||
|    * we cannot simply take a reference on the timelines and still | ||||
|    * use the list held by the master clock because the do_tick() | ||||
|    * might result in the creation of a new timeline, which gets | ||||
|    * added at the end of the list with no reference increase and | ||||
|    * thus gets disposed at the end of the iteration. | ||||
|    * | ||||
|    * this implies that a newly added timeline will not be advanced | ||||
|    * by this clock iteration, which is perfectly fine since we're | ||||
|    * in its first cycle. | ||||
|    * | ||||
|    * we also cannot steal the frame clock timelines list because | ||||
|    * a timeline might be removed as the direct result of do_tick() | ||||
|    * and remove_timeline() would not find the timeline, failing | ||||
|    * and leaving a dangling pointer behind. | ||||
|    */ | ||||
|  | ||||
|   timelines = g_list_copy (frame_clock->timelines); | ||||
|   g_list_foreach (timelines, (GFunc) g_object_ref, NULL); | ||||
|  | ||||
|   for (l = timelines; l; l = l->next) | ||||
|     { | ||||
|       ClutterTimeline *timeline = l->data; | ||||
|  | ||||
|       _clutter_timeline_do_tick (timeline, time_us / 1000); | ||||
|     } | ||||
|  | ||||
|   g_list_free_full (timelines, g_object_unref); | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_reschedule_update (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   if (frame_clock->pending_reschedule || | ||||
|       frame_clock->timelines) | ||||
|     { | ||||
|       frame_clock->pending_reschedule = FALSE; | ||||
|  | ||||
|       if (frame_clock->pending_reschedule_now) | ||||
|         { | ||||
|           frame_clock->pending_reschedule_now = FALSE; | ||||
|           clutter_frame_clock_schedule_update_now (frame_clock); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           clutter_frame_clock_schedule_update (frame_clock); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, | ||||
|                                       ClutterFrameInfo  *frame_info) | ||||
| { | ||||
|   int64_t presentation_time_us = frame_info->presentation_time; | ||||
|  | ||||
|   if (presentation_time_us > frame_clock->last_presentation_time_us || | ||||
|       ((presentation_time_us - frame_clock->last_presentation_time_us) > | ||||
|        INT64_MAX / 2)) | ||||
|     { | ||||
|       frame_clock->last_presentation_time_us = presentation_time_us; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_warning_once ("Bogus presentation time %" G_GINT64_FORMAT | ||||
|                       " travelled back in time, using current time.", | ||||
|                       presentation_time_us); | ||||
|       frame_clock->last_presentation_time_us = g_get_monotonic_time (); | ||||
|     } | ||||
|  | ||||
|   switch (frame_clock->state) | ||||
|     { | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_INIT: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_IDLE: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | ||||
|       g_warn_if_reached (); | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | ||||
|       frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; | ||||
|       maybe_reschedule_update (frame_clock); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| calculate_next_update_time_us (ClutterFrameClock *frame_clock, | ||||
|                                int64_t           *out_next_update_time_us, | ||||
|                                int64_t           *out_next_presentation_time_us) | ||||
| { | ||||
|   int64_t last_presentation_time_us; | ||||
|   int64_t now_us; | ||||
|   float refresh_rate; | ||||
|   int64_t refresh_interval_us; | ||||
|   int64_t min_render_time_allowed_us; | ||||
|   int64_t max_render_time_allowed_us; | ||||
|   int64_t last_next_presentation_time_us; | ||||
|   int64_t time_since_last_next_presentation_time_us; | ||||
|   int64_t next_presentation_time_us; | ||||
|   int64_t next_update_time_us; | ||||
|  | ||||
|   now_us = g_get_monotonic_time (); | ||||
|  | ||||
|   refresh_rate = frame_clock->refresh_rate; | ||||
|   refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate); | ||||
|  | ||||
|   min_render_time_allowed_us = refresh_interval_us / 2; | ||||
|   max_render_time_allowed_us = refresh_interval_us - SYNC_DELAY_US; | ||||
|  | ||||
|   if (min_render_time_allowed_us > max_render_time_allowed_us) | ||||
|     min_render_time_allowed_us = max_render_time_allowed_us; | ||||
|  | ||||
|   last_presentation_time_us = frame_clock->last_presentation_time_us; | ||||
|   next_presentation_time_us = last_presentation_time_us + refresh_interval_us; | ||||
|  | ||||
|   /* Skip ahead to get close to the actual next presentation time. */ | ||||
|   if (next_presentation_time_us < now_us) | ||||
|     { | ||||
|       int64_t logical_clock_offset_us; | ||||
|       int64_t logical_clock_phase_us; | ||||
|       int64_t hw_clock_offset_us; | ||||
|  | ||||
|       logical_clock_offset_us = now_us % refresh_interval_us; | ||||
|       logical_clock_phase_us = now_us - logical_clock_offset_us; | ||||
|       hw_clock_offset_us = last_presentation_time_us % refresh_interval_us; | ||||
|  | ||||
|       next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us; | ||||
|     } | ||||
|  | ||||
|   /* Skip one interval if we got an early presented event. */ | ||||
|   last_next_presentation_time_us = frame_clock->next_presentation_time_us; | ||||
|   time_since_last_next_presentation_time_us = | ||||
|       next_presentation_time_us - last_next_presentation_time_us; | ||||
|   if (frame_clock->is_next_presentation_time_valid && | ||||
|       time_since_last_next_presentation_time_us < (refresh_interval_us / 2)) | ||||
|     { | ||||
|       next_presentation_time_us = | ||||
|         frame_clock->next_presentation_time_us + refresh_interval_us; | ||||
|     } | ||||
|  | ||||
|   while (next_presentation_time_us < now_us + min_render_time_allowed_us) | ||||
|     next_presentation_time_us += refresh_interval_us; | ||||
|  | ||||
|   next_update_time_us = next_presentation_time_us - max_render_time_allowed_us; | ||||
|  | ||||
|   *out_next_update_time_us = next_update_time_us; | ||||
|   *out_next_presentation_time_us = next_presentation_time_us; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   frame_clock->inhibit_count++; | ||||
|  | ||||
|   if (frame_clock->inhibit_count == 1) | ||||
|     { | ||||
|       switch (frame_clock->state) | ||||
|         { | ||||
|         case CLUTTER_FRAME_CLOCK_STATE_INIT: | ||||
|         case CLUTTER_FRAME_CLOCK_STATE_IDLE: | ||||
|           break; | ||||
|         case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | ||||
|           frame_clock->pending_reschedule = TRUE; | ||||
|           frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; | ||||
|           break; | ||||
|         case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | ||||
|         case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       g_source_set_ready_time (frame_clock->source, -1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   g_return_if_fail (frame_clock->inhibit_count > 0); | ||||
|  | ||||
|   frame_clock->inhibit_count--; | ||||
|  | ||||
|   if (frame_clock->inhibit_count == 0) | ||||
|     maybe_reschedule_update (frame_clock); | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   int64_t next_update_time_us = -1; | ||||
|  | ||||
|   if (frame_clock->inhibit_count > 0) | ||||
|     { | ||||
|       frame_clock->pending_reschedule = TRUE; | ||||
|       frame_clock->pending_reschedule_now = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   switch (frame_clock->state) | ||||
|     { | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_INIT: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_IDLE: | ||||
|       next_update_time_us = g_get_monotonic_time (); | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | ||||
|       return; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | ||||
|       frame_clock->pending_reschedule = TRUE; | ||||
|       frame_clock->pending_reschedule_now = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   g_warn_if_fail (next_update_time_us != -1); | ||||
|  | ||||
|   g_source_set_ready_time (frame_clock->source, next_update_time_us); | ||||
|   frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; | ||||
|   frame_clock->is_next_presentation_time_valid = FALSE; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   int64_t next_update_time_us = -1; | ||||
|  | ||||
|   if (frame_clock->inhibit_count > 0) | ||||
|     { | ||||
|       frame_clock->pending_reschedule = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   switch (frame_clock->state) | ||||
|     { | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_INIT: | ||||
|       next_update_time_us = g_get_monotonic_time (); | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_IDLE: | ||||
|       calculate_next_update_time_us (frame_clock, | ||||
|                                      &next_update_time_us, | ||||
|                                      &frame_clock->next_presentation_time_us); | ||||
|       frame_clock->is_next_presentation_time_valid = TRUE; | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | ||||
|       return; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | ||||
|       frame_clock->pending_reschedule = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   g_warn_if_fail (next_update_time_us != -1); | ||||
|  | ||||
|   g_source_set_ready_time (frame_clock->source, next_update_time_us); | ||||
|   frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, | ||||
|                               int64_t            time_us) | ||||
| { | ||||
|   int64_t frame_count; | ||||
|   ClutterFrameResult result; | ||||
|  | ||||
|   COGL_TRACE_BEGIN_SCOPED (ClutterFrameCLockDispatch, "Frame Clock (dispatch)"); | ||||
|  | ||||
|   g_source_set_ready_time (frame_clock->source, -1); | ||||
|  | ||||
|   frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING; | ||||
|  | ||||
|   frame_count = frame_clock->frame_count++; | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterFrameClockEvents, "Frame Clock (before frame)"); | ||||
|   if (frame_clock->listener.iface->before_frame) | ||||
|     { | ||||
|       frame_clock->listener.iface->before_frame (frame_clock, | ||||
|                                                  frame_count, | ||||
|                                                  frame_clock->listener.user_data); | ||||
|     } | ||||
|   COGL_TRACE_END (ClutterFrameClockEvents); | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterFrameClockTimelines, "Frame Clock (timelines)"); | ||||
|   advance_timelines (frame_clock, time_us); | ||||
|   COGL_TRACE_END (ClutterFrameClockTimelines); | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterFrameClockFrame, "Frame Clock (frame)"); | ||||
|   result = frame_clock->listener.iface->frame (frame_clock, | ||||
|                                                frame_count, | ||||
|                                                time_us, | ||||
|                                                frame_clock->listener.user_data); | ||||
|   COGL_TRACE_END (ClutterFrameClockFrame); | ||||
|  | ||||
|   switch (frame_clock->state) | ||||
|     { | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_INIT: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: | ||||
|       g_warn_if_reached (); | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_IDLE: | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: | ||||
|       break; | ||||
|     case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: | ||||
|       switch (result) | ||||
|         { | ||||
|         case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: | ||||
|           frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED; | ||||
|           break; | ||||
|         case CLUTTER_FRAME_RESULT_IDLE: | ||||
|           frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; | ||||
|           maybe_reschedule_update (frame_clock); | ||||
|           break; | ||||
|         } | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| frame_clock_source_dispatch (GSource     *source, | ||||
|                              GSourceFunc  callback, | ||||
|                              gpointer     user_data) | ||||
| { | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|   ClutterFrameClock *frame_clock = clock_source->frame_clock; | ||||
|   int64_t dispatch_time_us; | ||||
|  | ||||
|   dispatch_time_us = g_source_get_time (source); | ||||
|   clutter_frame_clock_dispatch (frame_clock, dispatch_time_us); | ||||
|  | ||||
|   return G_SOURCE_CONTINUE; | ||||
| } | ||||
|  | ||||
| static GSourceFuncs frame_clock_source_funcs = { | ||||
|   NULL, | ||||
|   NULL, | ||||
|   frame_clock_source_dispatch, | ||||
|   NULL | ||||
| }; | ||||
|  | ||||
| static void | ||||
| init_frame_clock_source (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   GSource *source; | ||||
|   ClutterClockSource *clock_source; | ||||
|   g_autofree char *name = NULL; | ||||
|  | ||||
|   source = g_source_new (&frame_clock_source_funcs, sizeof (ClutterClockSource)); | ||||
|   clock_source = (ClutterClockSource *) source; | ||||
|  | ||||
|   name = g_strdup_printf ("Clutter frame clock (%p)", frame_clock); | ||||
|   g_source_set_name (source, name); | ||||
|   g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW); | ||||
|   g_source_set_can_recurse (source, FALSE); | ||||
|   clock_source->frame_clock = frame_clock; | ||||
|  | ||||
|   frame_clock->source = source; | ||||
|   g_source_attach (source, NULL); | ||||
| } | ||||
|  | ||||
| ClutterFrameClock * | ||||
| clutter_frame_clock_new (float                            refresh_rate, | ||||
|                          const ClutterFrameListenerIface *iface, | ||||
|                          gpointer                         user_data) | ||||
| { | ||||
|   ClutterFrameClock *frame_clock; | ||||
|  | ||||
|   g_assert_cmpfloat (refresh_rate, >, 0.0); | ||||
|  | ||||
|   frame_clock = g_object_new (CLUTTER_TYPE_FRAME_CLOCK, NULL); | ||||
|  | ||||
|   frame_clock->listener.iface = iface; | ||||
|   frame_clock->listener.user_data = user_data; | ||||
|  | ||||
|   init_frame_clock_source (frame_clock); | ||||
|  | ||||
|   frame_clock->refresh_rate = refresh_rate; | ||||
|  | ||||
|   return frame_clock; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_frame_clock_destroy (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   g_object_run_dispose (G_OBJECT (frame_clock)); | ||||
|   g_object_unref (frame_clock); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_frame_clock_dispose (GObject *object) | ||||
| { | ||||
| ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object); | ||||
|  | ||||
|   if (frame_clock->source) | ||||
|     { | ||||
|       g_signal_emit (frame_clock, signals[DESTROY], 0); | ||||
|       g_source_destroy (frame_clock->source); | ||||
|       g_clear_pointer (&frame_clock->source, g_source_unref); | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_frame_clock_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_frame_clock_init (ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_INIT; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_frame_clock_class_init (ClutterFrameClockClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = clutter_frame_clock_dispose; | ||||
|  | ||||
|   signals[DESTROY] = | ||||
|     g_signal_new (I_("destroy"), | ||||
|                   G_TYPE_FROM_CLASS (object_class), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, | ||||
|                   0); | ||||
| } | ||||
| @@ -1,87 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat Inc. | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef CLUTTER_FRAME_CLOCK_H | ||||
| #define CLUTTER_FRAME_CLOCK_H | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <glib-object.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #include "clutter/clutter-types.h" | ||||
|  | ||||
| typedef enum _ClutterFrameResult | ||||
| { | ||||
|   CLUTTER_FRAME_RESULT_PENDING_PRESENTED, | ||||
|   CLUTTER_FRAME_RESULT_IDLE, | ||||
| } ClutterFrameResult; | ||||
|  | ||||
| #define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ()) | ||||
| CLUTTER_EXPORT | ||||
| G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock, | ||||
|                       CLUTTER, FRAME_CLOCK, | ||||
|                       GObject) | ||||
|  | ||||
| typedef struct _ClutterFrameListenerIface | ||||
| { | ||||
|   void (* before_frame) (ClutterFrameClock *frame_clock, | ||||
|                          int64_t            frame_count, | ||||
|                          gpointer           user_data); | ||||
|   ClutterFrameResult (* frame) (ClutterFrameClock *frame_clock, | ||||
|                                 int64_t            frame_count, | ||||
|                                 int64_t            time_us, | ||||
|                                 gpointer           user_data); | ||||
| } ClutterFrameListenerIface; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterFrameClock * clutter_frame_clock_new (float                            refresh_rate, | ||||
|                                              const ClutterFrameListenerIface *iface, | ||||
|                                              gpointer                         user_data); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_destroy (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, | ||||
|                                            ClutterFrameInfo  *frame_info); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| void clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock, | ||||
|                                        ClutterTimeline   *timeline); | ||||
|  | ||||
| void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock, | ||||
|                                           ClutterTimeline   *timeline); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock); | ||||
|  | ||||
| #endif /* CLUTTER_FRAME_CLOCK_H */ | ||||
							
								
								
									
										96
									
								
								clutter/clutter/clutter-group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								clutter/clutter/clutter-group.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By Matthew Allum  <mallum@openedhand.com> | ||||
|  * | ||||
|  * 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, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_GROUP_H__ | ||||
| #define __CLUTTER_GROUP_H__ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter-types.h> | ||||
| #include <clutter/clutter-actor.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_GROUP              (clutter_group_get_type ()) | ||||
| #define CLUTTER_GROUP(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GROUP, ClutterGroup)) | ||||
| #define CLUTTER_GROUP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GROUP, ClutterGroupClass)) | ||||
| #define CLUTTER_IS_GROUP(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GROUP)) | ||||
| #define CLUTTER_IS_GROUP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GROUP)) | ||||
| #define CLUTTER_GROUP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GROUP, ClutterGroupClass)) | ||||
|  | ||||
| /* XXX - ClutterGroup is to be considered fully deprecated; the only | ||||
|  * reason we keep this header is because ClutterStage inherits from | ||||
|  * ClutterGroup, and thus we need to have a structure definition for | ||||
|  * the Stage object to expand. | ||||
|  */ | ||||
|  | ||||
| typedef struct _ClutterGroup            ClutterGroup; | ||||
| typedef struct _ClutterGroupClass       ClutterGroupClass; | ||||
| typedef struct _ClutterGroupPrivate     ClutterGroupPrivate; | ||||
|  | ||||
| /** | ||||
|  * ClutterGroup: | ||||
|  * | ||||
|  * The #ClutterGroup structure contains only private data | ||||
|  * and should be accessed using the provided API | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  */ | ||||
| struct _ClutterGroup | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   ClutterGroupPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * ClutterGroupClass: | ||||
|  * | ||||
|  * The #ClutterGroupClass structure contains only private data | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  */ | ||||
| struct _ClutterGroupClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   void (*_clutter_reserved1) (void); | ||||
|   void (*_clutter_reserved2) (void); | ||||
|   void (*_clutter_reserved3) (void); | ||||
|   void (*_clutter_reserved4) (void); | ||||
|   void (*_clutter_reserved5) (void); | ||||
|   void (*_clutter_reserved6) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_group_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_GROUP_H__ */ | ||||
| @@ -692,6 +692,20 @@ _clutter_input_device_free_touch_info (gpointer data) | ||||
|   g_slice_free (ClutterTouchInfo, data); | ||||
| } | ||||
|  | ||||
| static ClutterActor * | ||||
| _clutter_input_device_get_actor (ClutterInputDevice   *device, | ||||
|                                  ClutterEventSequence *sequence) | ||||
| { | ||||
|   ClutterTouchInfo *info; | ||||
|  | ||||
|   if (sequence == NULL) | ||||
|     return device->cursor_actor; | ||||
|  | ||||
|   info = g_hash_table_lookup (device->touch_sequences_info, sequence); | ||||
|  | ||||
|   return info->actor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| _clutter_input_device_associate_actor (ClutterInputDevice   *device, | ||||
|                                        ClutterEventSequence *sequence, | ||||
| @@ -801,7 +815,7 @@ _clutter_input_device_set_actor (ClutterInputDevice   *device, | ||||
|                                  ClutterActor         *actor, | ||||
|                                  gboolean              emit_crossing) | ||||
| { | ||||
|   ClutterActor *old_actor = clutter_input_device_get_actor (device, sequence); | ||||
|   ClutterActor *old_actor = _clutter_input_device_get_actor (device, sequence); | ||||
|  | ||||
|   if (old_actor == actor) | ||||
|     return; | ||||
| @@ -836,7 +850,7 @@ _clutter_input_device_set_actor (ClutterInputDevice   *device, | ||||
|         } | ||||
|  | ||||
|       /* processing the event might have destroyed the actor */ | ||||
|       tmp_old_actor = clutter_input_device_get_actor (device, sequence); | ||||
|       tmp_old_actor = _clutter_input_device_get_actor (device, sequence); | ||||
|       _clutter_input_device_unassociate_actor (device, | ||||
|                                                old_actor, | ||||
|                                                tmp_old_actor == NULL); | ||||
| @@ -1040,7 +1054,7 @@ clutter_input_device_update (ClutterInputDevice   *device, | ||||
|  | ||||
|   clutter_input_device_get_coords (device, sequence, &point); | ||||
|  | ||||
|   old_cursor_actor = clutter_input_device_get_actor (device, sequence); | ||||
|   old_cursor_actor = _clutter_input_device_get_actor (device, sequence); | ||||
|   new_cursor_actor = | ||||
|     _clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE); | ||||
|  | ||||
| @@ -1071,33 +1085,22 @@ clutter_input_device_update (ClutterInputDevice   *device, | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_input_device_get_actor: | ||||
|  * @device: a #ClutterInputDevice | ||||
|  * @sequence: (allow-none): an optional #ClutterEventSequence | ||||
|  * clutter_input_device_get_pointer_actor: | ||||
|  * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE | ||||
|  * | ||||
|  * Retrieves the #ClutterActor underneath the pointer or touchpoint | ||||
|  * of @device and @sequence. | ||||
|  * Retrieves the #ClutterActor underneath the pointer of @device | ||||
|  * | ||||
|  * Return value: (transfer none): a pointer to the #ClutterActor or %NULL | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_input_device_get_actor (ClutterInputDevice   *device, | ||||
|                                 ClutterEventSequence *sequence) | ||||
| clutter_input_device_get_pointer_actor (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterTouchInfo *info; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); | ||||
|   g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL); | ||||
|  | ||||
|   if (sequence == NULL) | ||||
|     return device->cursor_actor; | ||||
|  | ||||
|   info = g_hash_table_lookup (device->touch_sequences_info, sequence); | ||||
|  | ||||
|   g_return_val_if_fail (info != NULL, NULL); | ||||
|  | ||||
|   return info->actor; | ||||
|   return device->cursor_actor; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -92,8 +92,7 @@ gboolean                clutter_input_device_get_coords        (ClutterInputDevi | ||||
| CLUTTER_EXPORT | ||||
| ClutterModifierType     clutter_input_device_get_modifier_state (ClutterInputDevice  *device); | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor *          clutter_input_device_get_actor (ClutterInputDevice   *device, | ||||
|                                                         ClutterEventSequence *sequence); | ||||
| ClutterActor *          clutter_input_device_get_pointer_actor  (ClutterInputDevice  *device); | ||||
| CLUTTER_EXPORT | ||||
| ClutterStage *          clutter_input_device_get_pointer_stage  (ClutterInputDevice  *device); | ||||
| CLUTTER_EXPORT | ||||
|   | ||||
| @@ -32,7 +32,8 @@ | ||||
|  * it has been paired, and it controls the allocation of its children. | ||||
|  * | ||||
|  * Any composite or container #ClutterActor subclass can delegate the | ||||
|  * layouting of its children to a #ClutterLayoutManager. | ||||
|  * layouting of its children to a #ClutterLayoutManager. Clutter provides | ||||
|  * a generic container using #ClutterLayoutManager called #ClutterBox. | ||||
|  * | ||||
|  * Clutter provides some simple #ClutterLayoutManager sub-classes, like | ||||
|  * #ClutterFlowLayout and #ClutterBinLayout. | ||||
| @@ -96,7 +97,7 @@ | ||||
|  * | ||||
|  * |[ | ||||
|  * { | ||||
|  *   "type" : "ClutterActor", | ||||
|  *   "type" : "ClutterBox", | ||||
|  *   "layout-manager" : { "type" : "ClutterGridLayout" }, | ||||
|  *   "children" : [ | ||||
|  *     { | ||||
|   | ||||
| @@ -61,6 +61,7 @@ | ||||
| #include "clutter-input-pointer-a11y-private.h" | ||||
| #include "clutter-graphene.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-mutter.h" | ||||
| #include "clutter-paint-node-private.h" | ||||
| #include "clutter-private.h" | ||||
| @@ -82,6 +83,10 @@ | ||||
|  | ||||
| /* main context */ | ||||
| static ClutterMainContext *ClutterCntx       = NULL; | ||||
| G_LOCK_DEFINE_STATIC (ClutterCntx); | ||||
|  | ||||
| /* main lock and locking/unlocking functions */ | ||||
| static GMutex clutter_threads_mutex; | ||||
|  | ||||
| /* command line options */ | ||||
| static gboolean clutter_is_initialized       = FALSE; | ||||
| @@ -140,6 +145,12 @@ static const GDebugKey clutter_paint_debug_keys[] = { | ||||
|   { "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION }, | ||||
| }; | ||||
|  | ||||
| static inline void | ||||
| clutter_threads_init_default (void) | ||||
| { | ||||
|   g_mutex_init (&clutter_threads_mutex); | ||||
| } | ||||
|  | ||||
| #define ENVIRONMENT_GROUP       "Environment" | ||||
| #define DEBUG_GROUP             "Debug" | ||||
|  | ||||
| @@ -508,7 +519,11 @@ clutter_main (void) | ||||
|   main_loops = g_slist_prepend (main_loops, loop); | ||||
|  | ||||
|   if (g_main_loop_is_running (main_loops->data)) | ||||
|     g_main_loop_run (loop); | ||||
|     { | ||||
|       _clutter_threads_release_lock (); | ||||
|       g_main_loop_run (loop); | ||||
|       _clutter_threads_acquire_lock (); | ||||
|     } | ||||
|  | ||||
|   main_loops = g_slist_remove (main_loops, loop); | ||||
|  | ||||
| @@ -525,9 +540,13 @@ _clutter_threads_dispatch (gpointer data) | ||||
|   ClutterThreadsDispatch *dispatch = data; | ||||
|   gboolean ret = FALSE; | ||||
|  | ||||
|   _clutter_threads_acquire_lock (); | ||||
|  | ||||
|   if (!g_source_is_destroyed (g_main_current_source ())) | ||||
|     ret = dispatch->func (dispatch->data); | ||||
|  | ||||
|   _clutter_threads_release_lock (); | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| @@ -752,6 +771,40 @@ clutter_threads_add_timeout (guint       interval, | ||||
|                                            NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_threads_acquire_lock (void) | ||||
| { | ||||
|   g_mutex_lock (&clutter_threads_mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_threads_release_lock (void) | ||||
| { | ||||
|   /* we need to trylock here, in case the lock hasn't been acquired; on | ||||
|    * various systems trying to release a mutex that hasn't been acquired | ||||
|    * will cause a run-time error. trylock() will either fail, in which | ||||
|    * case we can release the lock we own; or it will succeeds, in which | ||||
|    * case we need to release the lock we just acquired. so we ignore the | ||||
|    * returned value. | ||||
|    * | ||||
|    * see: https://bugs.gnome.org/679439 | ||||
|    */ | ||||
|   g_mutex_trylock (&clutter_threads_mutex); | ||||
|   g_mutex_unlock (&clutter_threads_mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_context_lock (void) | ||||
| { | ||||
|   G_LOCK (ClutterCntx); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_context_unlock (void) | ||||
| { | ||||
|   G_UNLOCK (ClutterCntx); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_context_is_initialized (void) | ||||
| { | ||||
| @@ -761,8 +814,8 @@ _clutter_context_is_initialized (void) | ||||
|   return ClutterCntx->is_initialized; | ||||
| } | ||||
|  | ||||
| ClutterMainContext * | ||||
| _clutter_context_get_default (void) | ||||
| static ClutterMainContext * | ||||
| clutter_context_get_default_unlocked (void) | ||||
| { | ||||
|   if (G_UNLIKELY (ClutterCntx == NULL)) | ||||
|     { | ||||
| @@ -793,6 +846,20 @@ _clutter_context_get_default (void) | ||||
|   return ClutterCntx; | ||||
| } | ||||
|  | ||||
| ClutterMainContext * | ||||
| _clutter_context_get_default (void) | ||||
| { | ||||
|   ClutterMainContext *retval; | ||||
|  | ||||
|   _clutter_context_lock (); | ||||
|  | ||||
|   retval = clutter_context_get_default_unlocked (); | ||||
|  | ||||
|   _clutter_context_unlock (); | ||||
|  | ||||
|   return retval; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_arg_direction_cb (const char *key, | ||||
|                           const char *value, | ||||
| @@ -1982,8 +2049,7 @@ _clutter_process_event_details (ClutterActor        *stage, | ||||
|  | ||||
|                   emit_touch_event (event, device); | ||||
|  | ||||
|                   if (event->type == CLUTTER_TOUCH_END || | ||||
|                       event->type == CLUTTER_TOUCH_CANCEL) | ||||
|                   if (event->type == CLUTTER_TOUCH_END) | ||||
|                     _clutter_input_device_remove_event_sequence (device, event); | ||||
|  | ||||
|                   break; | ||||
| @@ -2018,8 +2084,7 @@ _clutter_process_event_details (ClutterActor        *stage, | ||||
|  | ||||
|           emit_touch_event (event, device); | ||||
|  | ||||
|           if (event->type == CLUTTER_TOUCH_END || | ||||
|               event->type == CLUTTER_TOUCH_CANCEL) | ||||
|           if (event->type == CLUTTER_TOUCH_END) | ||||
|             _clutter_input_device_remove_event_sequence (device, event); | ||||
|  | ||||
|           break; | ||||
| @@ -2089,6 +2154,27 @@ _clutter_process_event (ClutterEvent *event) | ||||
|   context->current_event = g_slist_delete_link (context->current_event, context->current_event); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_get_actor_by_gid: | ||||
|  * @id_: a #ClutterActor unique id. | ||||
|  * | ||||
|  * Retrieves the #ClutterActor with @id_. | ||||
|  * | ||||
|  * Return value: (transfer none): the actor with the passed id or %NULL. | ||||
|  *   The returned actor does not have its reference count increased. | ||||
|  * | ||||
|  * Since: 0.6 | ||||
|  * | ||||
|  * Deprecated: 1.8: The id is deprecated, and this function always returns | ||||
|  *   %NULL. Use the proper scene graph API in #ClutterActor to find a child | ||||
|  *   of the stage. | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_get_actor_by_gid (guint32 id_) | ||||
| { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_base_init (void) | ||||
| { | ||||
| @@ -2103,6 +2189,9 @@ clutter_base_init (void) | ||||
|       g_type_init (); | ||||
| #endif | ||||
|  | ||||
|       /* initialise the Big Clutter Lock™ if necessary */ | ||||
|       clutter_threads_init_default (); | ||||
|  | ||||
|       clutter_graphene_init (); | ||||
|     } | ||||
| } | ||||
| @@ -2170,7 +2259,9 @@ clutter_threads_remove_repaint_func (guint handle_id) | ||||
|  | ||||
|   g_return_if_fail (handle_id > 0); | ||||
|  | ||||
|   context = _clutter_context_get_default (); | ||||
|   _clutter_context_lock (); | ||||
|  | ||||
|   context = clutter_context_get_default_unlocked (); | ||||
|   l = context->repaint_funcs; | ||||
|   while (l != NULL) | ||||
|     { | ||||
| @@ -2193,6 +2284,8 @@ clutter_threads_remove_repaint_func (guint handle_id) | ||||
|  | ||||
|       l = l->next; | ||||
|     } | ||||
|  | ||||
|   _clutter_context_unlock (); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -2291,13 +2384,16 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags, | ||||
|  | ||||
|   g_return_val_if_fail (func != NULL, 0); | ||||
|  | ||||
|   context = _clutter_context_get_default (); | ||||
|   _clutter_context_lock (); | ||||
|  | ||||
|   context = clutter_context_get_default_unlocked (); | ||||
|  | ||||
|   repaint_func = g_slice_new (ClutterRepaintFunction); | ||||
|  | ||||
|   repaint_func->id = context->last_repaint_id++; | ||||
|  | ||||
|   repaint_func->flags = flags; | ||||
|   /* mask out QUEUE_REDRAW_ON_ADD, since we're going to consume it */ | ||||
|   repaint_func->flags = flags & ~CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD; | ||||
|   repaint_func->func = func; | ||||
|   repaint_func->data = data; | ||||
|   repaint_func->notify = notify; | ||||
| @@ -2305,6 +2401,15 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags, | ||||
|   context->repaint_funcs = g_list_prepend (context->repaint_funcs, | ||||
|                                            repaint_func); | ||||
|  | ||||
|   _clutter_context_unlock (); | ||||
|  | ||||
|   if ((flags & CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD) != 0) | ||||
|     { | ||||
|       ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); | ||||
|  | ||||
|       _clutter_master_clock_ensure_next_iteration (master_clock); | ||||
|     } | ||||
|  | ||||
|   return repaint_func->id; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										618
									
								
								clutter/clutter/clutter-master-clock-default.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										618
									
								
								clutter/clutter/clutter-master-clock-default.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,618 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  * Copyright (C) 2009  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/>. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * SECTION:clutter-master-clock-default | ||||
|  * @short_description: The default master clock for all animations | ||||
|  * | ||||
|  * The #ClutterMasterClockDefault class is the default implementation | ||||
|  * of #ClutterMasterClock. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-master-clock-default.h" | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-stage-manager-private.h" | ||||
| #include "clutter-stage-private.h" | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
| #define clutter_warn_if_over_budget(master_clock,start_time,section)    G_STMT_START  { \ | ||||
|   gint64 __delta = g_get_monotonic_time () - start_time;                                \ | ||||
|   gint64 __budget = master_clock->remaining_budget;                                     \ | ||||
|   if (__budget > 0 && __delta >= __budget) {                                            \ | ||||
|     _clutter_diagnostic_message ("%s took %" G_GINT64_FORMAT " microseconds "           \ | ||||
|                                  "more than the remaining budget of %" G_GINT64_FORMAT  \ | ||||
|                                  " microseconds",                                       \ | ||||
|                                  section, __delta - __budget, __budget);                \ | ||||
|   }                                                                     } G_STMT_END | ||||
| #else | ||||
| #define clutter_warn_if_over_budget(master_clock,start_time,section) | ||||
| #endif | ||||
|  | ||||
| typedef struct _ClutterClockSource              ClutterClockSource; | ||||
|  | ||||
| struct _ClutterMasterClockDefault | ||||
| { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   /* the list of timelines handled by the clock */ | ||||
|   GSList *timelines; | ||||
|  | ||||
|   /* the current state of the clock, in usecs */ | ||||
|   gint64 cur_tick; | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   gint64 frame_budget; | ||||
|   gint64 remaining_budget; | ||||
| #endif | ||||
|  | ||||
|   /* an idle source, used by the Master Clock to queue | ||||
|    * a redraw on the stage and drive the animations | ||||
|    */ | ||||
|   GSource *source; | ||||
|  | ||||
|   guint ensure_next_iteration : 1; | ||||
|  | ||||
|   guint paused : 1; | ||||
| }; | ||||
|  | ||||
| struct _ClutterClockSource | ||||
| { | ||||
|   GSource source; | ||||
|  | ||||
|   ClutterMasterClockDefault *master_clock; | ||||
| }; | ||||
|  | ||||
| static gboolean clutter_clock_prepare  (GSource     *source, | ||||
|                                         gint        *timeout); | ||||
| static gboolean clutter_clock_check    (GSource     *source); | ||||
| static gboolean clutter_clock_dispatch (GSource     *source, | ||||
|                                         GSourceFunc  callback, | ||||
|                                         gpointer     user_data); | ||||
|  | ||||
| static GSourceFuncs clock_funcs = { | ||||
|   clutter_clock_prepare, | ||||
|   clutter_clock_check, | ||||
|   clutter_clock_dispatch, | ||||
|   NULL | ||||
| }; | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_iface_init (ClutterMasterClockInterface *iface); | ||||
|  | ||||
| #define clutter_master_clock_default_get_type   _clutter_master_clock_default_get_type | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (ClutterMasterClockDefault, | ||||
|                          clutter_master_clock_default, | ||||
|                          G_TYPE_OBJECT, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_MASTER_CLOCK, | ||||
|                                                 clutter_master_clock_iface_init)); | ||||
|  | ||||
| /* | ||||
|  * master_clock_is_running: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * | ||||
|  * Checks if we should currently be advancing timelines or redrawing | ||||
|  * stages. | ||||
|  * | ||||
|  * Return value: %TRUE if the #ClutterMasterClock has at least | ||||
|  *   one running timeline | ||||
|  */ | ||||
| static gboolean | ||||
| master_clock_is_running (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); | ||||
|   const GSList *stages, *l; | ||||
|  | ||||
|   stages = clutter_stage_manager_peek_stages (stage_manager); | ||||
|  | ||||
|   if (master_clock->paused) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (master_clock->timelines) | ||||
|     return TRUE; | ||||
|  | ||||
|   for (l = stages; l; l = l->next) | ||||
|     { | ||||
|       if (clutter_actor_is_mapped (l->data) && | ||||
|           (_clutter_stage_has_queued_events (l->data) || | ||||
|            _clutter_stage_needs_update (l->data))) | ||||
|         return TRUE; | ||||
|     } | ||||
|  | ||||
|   if (master_clock->ensure_next_iteration) | ||||
|     { | ||||
|       master_clock->ensure_next_iteration = FALSE; | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gint | ||||
| master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); | ||||
|   const GSList *stages, *l; | ||||
|   gint64 min_update_time = -1; | ||||
|  | ||||
|   stages = clutter_stage_manager_peek_stages (stage_manager); | ||||
|  | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     { | ||||
|       gint64 update_time = _clutter_stage_get_update_time (l->data); | ||||
|       if (min_update_time == -1 || | ||||
|           (update_time != -1 && update_time < min_update_time)) | ||||
|         min_update_time = update_time; | ||||
|     } | ||||
|  | ||||
|   if (min_update_time == -1) | ||||
|     { | ||||
|       return -1; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       gint64 now = g_source_get_time (master_clock->source); | ||||
|       if (min_update_time < now) | ||||
|         { | ||||
|           return 0; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           gint64 delay_us = min_update_time - now; | ||||
|           return (delay_us + 999) / 1000; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); | ||||
|   const GSList *stages, *l; | ||||
|  | ||||
|   stages = clutter_stage_manager_peek_stages (stage_manager); | ||||
|  | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     clutter_stage_schedule_update (l->data); | ||||
| } | ||||
|  | ||||
| static GSList * | ||||
| master_clock_list_ready_stages (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); | ||||
|   const GSList *stages, *l; | ||||
|   GSList *result; | ||||
|  | ||||
|   stages = clutter_stage_manager_peek_stages (stage_manager); | ||||
|  | ||||
|   result = NULL; | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     { | ||||
|       gint64 update_time = _clutter_stage_get_update_time (l->data); | ||||
|       /* We carefully avoid to update stages that aren't mapped, because | ||||
|        * they have nothing to render and this could cause a deadlock with | ||||
|        * some of the SwapBuffers implementations (in particular | ||||
|        * GLX_INTEL_swap_event is not emitted if nothing was rendered). | ||||
|        * | ||||
|        * Also, if a stage has a swap-buffers pending we don't want to draw | ||||
|        * to it in case the driver may block the CPU while it waits for the | ||||
|        * next backbuffer to become available. | ||||
|        * | ||||
|        * TODO: We should be able to identify if we are running triple or N | ||||
|        * buffered and in these cases we can still draw if there is 1 swap | ||||
|        * pending so we can hopefully always be ready to swap for the next | ||||
|        * vblank and really match the vsync frequency. | ||||
|        */ | ||||
|       if (clutter_actor_is_mapped (l->data) && | ||||
|           update_time != -1 && update_time <= master_clock->cur_tick) | ||||
|         result = g_slist_prepend (result, g_object_ref (l->data)); | ||||
|     } | ||||
|  | ||||
|   return g_slist_reverse (result); | ||||
| } | ||||
|  | ||||
| static void | ||||
| master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock, | ||||
|                                        GSList                    *stages) | ||||
| { | ||||
|   const GSList *l; | ||||
|  | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     { | ||||
|       /* Clear the old update time */ | ||||
|       _clutter_stage_clear_update_time (l->data); | ||||
|  | ||||
|       /* And if there is still work to be done, schedule a new one */ | ||||
|       if (master_clock->timelines || | ||||
|           _clutter_stage_has_queued_events (l->data) || | ||||
|           _clutter_stage_needs_update (l->data)) | ||||
|         clutter_stage_schedule_update (l->data); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * master_clock_next_frame_delay: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * | ||||
|  * Computes the number of delay before we need to draw the next frame. | ||||
|  * | ||||
|  * Return value: -1 if there is no next frame pending, otherwise the | ||||
|  *  number of millseconds before the we need to draw the next frame | ||||
|  */ | ||||
| static gint | ||||
| master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   if (!master_clock_is_running (master_clock)) | ||||
|     return -1; | ||||
|  | ||||
|   /* If all of the stages are busy waiting for a swap-buffers to complete | ||||
|    * then we wait for one to be ready.. */ | ||||
|   return master_clock_get_swap_wait_time (master_clock); | ||||
| } | ||||
|  | ||||
| static void | ||||
| master_clock_process_events (ClutterMasterClockDefault *master_clock, | ||||
|                              GSList                    *stages) | ||||
| { | ||||
|   GSList *l; | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   gint64 start = g_get_monotonic_time (); | ||||
| #endif | ||||
|  | ||||
|   /* Process queued events */ | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     _clutter_stage_process_queued_events (l->data); | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   if (_clutter_diagnostic_enabled ()) | ||||
|     clutter_warn_if_over_budget (master_clock, start, "Event processing"); | ||||
|  | ||||
|   master_clock->remaining_budget -= (g_get_monotonic_time () - start); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * master_clock_advance_timelines: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * | ||||
|  * Advances all the timelines held by the master clock. This function | ||||
|  * should be called before calling _clutter_stage_do_update() to | ||||
|  * make sure that all the timelines are advanced and the scene is updated. | ||||
|  */ | ||||
| static void | ||||
| master_clock_advance_timelines (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   GSList *timelines, *l; | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   gint64 start = g_get_monotonic_time (); | ||||
| #endif | ||||
|  | ||||
|   /* we protect ourselves from timelines being removed during | ||||
|    * the advancement by other timelines by copying the list of | ||||
|    * timelines, taking a reference on them, iterating over the | ||||
|    * copied list and then releasing the reference. | ||||
|    * | ||||
|    * we cannot simply take a reference on the timelines and still | ||||
|    * use the list held by the master clock because the do_tick() | ||||
|    * might result in the creation of a new timeline, which gets | ||||
|    * added at the end of the list with no reference increase and | ||||
|    * thus gets disposed at the end of the iteration. | ||||
|    * | ||||
|    * this implies that a newly added timeline will not be advanced | ||||
|    * by this clock iteration, which is perfectly fine since we're | ||||
|    * in its first cycle. | ||||
|    * | ||||
|    * we also cannot steal the master clock timelines list because | ||||
|    * a timeline might be removed as the direct result of do_tick() | ||||
|    * and remove_timeline() would not find the timeline, failing | ||||
|    * and leaving a dangling pointer behind. | ||||
|    */ | ||||
|   timelines = g_slist_copy (master_clock->timelines); | ||||
|   g_slist_foreach (timelines, (GFunc) g_object_ref, NULL); | ||||
|  | ||||
|   for (l = timelines; l != NULL; l = l->next) | ||||
|     _clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000); | ||||
|  | ||||
|   g_slist_free_full (timelines, g_object_unref); | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   if (_clutter_diagnostic_enabled ()) | ||||
|     clutter_warn_if_over_budget (master_clock, start, "Animations"); | ||||
|  | ||||
|   master_clock->remaining_budget -= (g_get_monotonic_time () - start); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| master_clock_update_stages (ClutterMasterClockDefault *master_clock, | ||||
|                             GSList                    *stages) | ||||
| { | ||||
|   gboolean stages_updated = FALSE; | ||||
|   GSList *l; | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   gint64 start = g_get_monotonic_time (); | ||||
| #endif | ||||
|  | ||||
|   _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT); | ||||
|  | ||||
|   /* Update any stage that needs redraw/relayout after the clock | ||||
|    * is advanced. | ||||
|    */ | ||||
|   for (l = stages; l != NULL; l = l->next) | ||||
|     stages_updated |= _clutter_stage_do_update (l->data); | ||||
|  | ||||
|   _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT); | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   if (_clutter_diagnostic_enabled ()) | ||||
|     clutter_warn_if_over_budget (master_clock, start, "Updating the stage"); | ||||
|  | ||||
|   master_clock->remaining_budget -= (g_get_monotonic_time () - start); | ||||
| #endif | ||||
|  | ||||
|   return stages_updated; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * clutter_clock_source_new: | ||||
|  * @master_clock: a #ClutterMasterClock for the source | ||||
|  * | ||||
|  * The #ClutterClockSource is an idle GSource that will queue a redraw | ||||
|  * if @master_clock has at least a running #ClutterTimeline. The redraw | ||||
|  * will cause @master_clock to advance all timelines, thus advancing all | ||||
|  * animations as well. | ||||
|  * | ||||
|  * Return value: the newly created #GSource | ||||
|  */ | ||||
| static GSource * | ||||
| clutter_clock_source_new (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   GSource *source = g_source_new (&clock_funcs, sizeof (ClutterClockSource)); | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|  | ||||
|   g_source_set_name (source, "Clutter master clock"); | ||||
|   g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW); | ||||
|   g_source_set_can_recurse (source, FALSE); | ||||
|   clock_source->master_clock = master_clock; | ||||
|  | ||||
|   return source; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_clock_prepare (GSource *source, | ||||
|                        gint    *timeout) | ||||
| { | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|   ClutterMasterClockDefault *master_clock = clock_source->master_clock; | ||||
|   int delay; | ||||
|  | ||||
|   _clutter_threads_acquire_lock (); | ||||
|  | ||||
|   if (G_UNLIKELY (clutter_paint_debug_flags & | ||||
|                   CLUTTER_DEBUG_CONTINUOUS_REDRAW)) | ||||
|     { | ||||
|       ClutterStageManager *stage_manager = clutter_stage_manager_get_default (); | ||||
|       const GSList *stages, *l; | ||||
|  | ||||
|       stages = clutter_stage_manager_peek_stages (stage_manager); | ||||
|  | ||||
|       /* Queue a full redraw on all of the stages */ | ||||
|       for (l = stages; l != NULL; l = l->next) | ||||
|         clutter_actor_queue_redraw (l->data); | ||||
|     } | ||||
|  | ||||
|   delay = master_clock_next_frame_delay (master_clock); | ||||
|  | ||||
|   _clutter_threads_release_lock (); | ||||
|  | ||||
|   *timeout = delay; | ||||
|  | ||||
|   return delay == 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_clock_check (GSource *source) | ||||
| { | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|   ClutterMasterClockDefault *master_clock = clock_source->master_clock; | ||||
|   int delay; | ||||
|  | ||||
|   _clutter_threads_acquire_lock (); | ||||
|   delay = master_clock_next_frame_delay (master_clock); | ||||
|   _clutter_threads_release_lock (); | ||||
|  | ||||
|   return delay == 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_clock_dispatch (GSource     *source, | ||||
|                         GSourceFunc  callback, | ||||
|                         gpointer     user_data) | ||||
| { | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|   ClutterMasterClockDefault *master_clock = clock_source->master_clock; | ||||
|   GSList *stages; | ||||
|  | ||||
|   CLUTTER_NOTE (SCHEDULER, "Master clock [tick]"); | ||||
|  | ||||
|   _clutter_threads_acquire_lock (); | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)"); | ||||
|  | ||||
|   /* Get the time to use for this frame */ | ||||
|   master_clock->cur_tick = g_source_get_time (source); | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   master_clock->remaining_budget = master_clock->frame_budget; | ||||
| #endif | ||||
|  | ||||
|   /* We need to protect ourselves against stages being destroyed during | ||||
|    * event handling - master_clock_list_ready_stages() returns a | ||||
|    * list of referenced that we'll unref afterwards. | ||||
|    */ | ||||
|   stages = master_clock_list_ready_stages (master_clock); | ||||
|  | ||||
|   /* Each frame is split into three separate phases: */ | ||||
|  | ||||
|   /* 1. process all the events; each stage goes through its events queue | ||||
|    *    and processes each event according to its type, then emits the | ||||
|    *    various signals that are associated with the event | ||||
|    */ | ||||
|   master_clock_process_events (master_clock, stages); | ||||
|  | ||||
|   /* 2. advance the timelines */ | ||||
|   master_clock_advance_timelines (master_clock); | ||||
|  | ||||
|   /* 3. relayout and redraw the stages */ | ||||
|   master_clock_update_stages (master_clock, stages); | ||||
|  | ||||
|   master_clock_reschedule_stage_updates (master_clock, stages); | ||||
|  | ||||
|   g_slist_free_full (stages, g_object_unref); | ||||
|  | ||||
|   COGL_TRACE_END (ClutterMasterClockTick); | ||||
|  | ||||
|   _clutter_threads_release_lock (); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_finalize (GObject *gobject) | ||||
| { | ||||
|   ClutterMasterClockDefault *master_clock = CLUTTER_MASTER_CLOCK_DEFAULT (gobject); | ||||
|  | ||||
|   g_slist_free (master_clock->timelines); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_master_clock_default_parent_class)->finalize (gobject); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_class_init (ClutterMasterClockDefaultClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   gobject_class->finalize = clutter_master_clock_default_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_init (ClutterMasterClockDefault *self) | ||||
| { | ||||
|   GSource *source; | ||||
|  | ||||
|   source = clutter_clock_source_new (self); | ||||
|   self->source = source; | ||||
|  | ||||
|   self->ensure_next_iteration = FALSE; | ||||
|   self->paused = FALSE; | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   self->frame_budget = G_USEC_PER_SEC / 60; | ||||
| #endif | ||||
|  | ||||
|   g_source_attach (source, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_add_timeline (ClutterMasterClock *clock, | ||||
|                                            ClutterTimeline    *timeline) | ||||
| { | ||||
|   ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; | ||||
|   gboolean is_first; | ||||
|  | ||||
|   if (g_slist_find (master_clock->timelines, timeline)) | ||||
|     return; | ||||
|  | ||||
|   is_first = master_clock->timelines == NULL; | ||||
|  | ||||
|   master_clock->timelines = g_slist_prepend (master_clock->timelines, | ||||
|                                              timeline); | ||||
|  | ||||
|   if (is_first) | ||||
|     { | ||||
|       master_clock_schedule_stage_updates (master_clock); | ||||
|       _clutter_master_clock_start_running (clock); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_remove_timeline (ClutterMasterClock *clock, | ||||
|                                               ClutterTimeline    *timeline) | ||||
| { | ||||
|   ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; | ||||
|  | ||||
|   master_clock->timelines = g_slist_remove (master_clock->timelines, | ||||
|                                             timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_start_running (ClutterMasterClock *master_clock) | ||||
| { | ||||
|   /* If called from a different thread, we need to wake up the | ||||
|    * main loop to start running the timelines | ||||
|    */ | ||||
|   g_main_context_wakeup (NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_ensure_next_iteration (ClutterMasterClock *clock) | ||||
| { | ||||
|   ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; | ||||
|  | ||||
|   master_clock->ensure_next_iteration = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_set_paused (ClutterMasterClock *clock, | ||||
|                                          gboolean            paused) | ||||
| { | ||||
|   ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock; | ||||
|  | ||||
|   if (paused && !master_clock->paused) | ||||
|     { | ||||
|       g_clear_pointer (&master_clock->source, g_source_destroy); | ||||
|     } | ||||
|   else if (!paused && master_clock->paused) | ||||
|     { | ||||
|       master_clock->source = clutter_clock_source_new (master_clock); | ||||
|       g_source_attach (master_clock->source, NULL); | ||||
|     } | ||||
|  | ||||
|   master_clock->paused = !!paused; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_iface_init (ClutterMasterClockInterface *iface) | ||||
| { | ||||
|   iface->add_timeline = clutter_master_clock_default_add_timeline; | ||||
|   iface->remove_timeline = clutter_master_clock_default_remove_timeline; | ||||
|   iface->start_running = clutter_master_clock_default_start_running; | ||||
|   iface->ensure_next_iteration = clutter_master_clock_default_ensure_next_iteration; | ||||
|   iface->set_paused = clutter_master_clock_default_set_paused; | ||||
| } | ||||
							
								
								
									
										48
									
								
								clutter/clutter/clutter-master-clock-default.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								clutter/clutter/clutter-master-clock-default.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com> | ||||
|  * | ||||
|  * Copyright (C) 2015  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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_MASTER_CLOCK_DEFAULT_H__ | ||||
| #define __CLUTTER_MASTER_CLOCK_DEFAULT_H__ | ||||
|  | ||||
| #include <clutter/clutter-timeline.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_MASTER_CLOCK_DEFAULT            (_clutter_master_clock_default_get_type ()) | ||||
| #define CLUTTER_MASTER_CLOCK_DEFAULT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefault)) | ||||
| #define CLUTTER_IS_MASTER_CLOCK_DEFAULT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT)) | ||||
| #define CLUTTER_MASTER_CLOCK_DEFAULT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefaultClass)) | ||||
|  | ||||
| typedef struct _ClutterMasterClockDefault      ClutterMasterClockDefault; | ||||
| typedef struct _ClutterMasterClockDefaultClass ClutterMasterClockDefaultClass; | ||||
|  | ||||
| struct _ClutterMasterClockDefaultClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType _clutter_master_clock_default_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_MASTER_CLOCK_DEFAULT_H__ */ | ||||
							
								
								
									
										132
									
								
								clutter/clutter/clutter-master-clock.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								clutter/clutter/clutter-master-clock.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  * Copyright (C) 2009  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/>. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * SECTION:clutter-master-clock | ||||
|  * @short_description: The master clock for all animations | ||||
|  * | ||||
|  * The #ClutterMasterClock class is responsible for advancing all | ||||
|  * #ClutterTimelines when a stage is being redrawn. The master clock | ||||
|  * makes sure that the scenegraph is always integrally updated before | ||||
|  * painting it. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-master-clock-default.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| G_DEFINE_INTERFACE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT) | ||||
|  | ||||
| static void | ||||
| clutter_master_clock_default_init (ClutterMasterClockInterface *iface) | ||||
| { | ||||
| } | ||||
|  | ||||
| ClutterMasterClock * | ||||
| _clutter_master_clock_get_default (void) | ||||
| { | ||||
|   ClutterMainContext *context = _clutter_context_get_default (); | ||||
|  | ||||
|   if (G_UNLIKELY (context->master_clock == NULL)) | ||||
|     context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL); | ||||
|  | ||||
|   return context->master_clock; | ||||
|  | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * _clutter_master_clock_add_timeline: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * | ||||
|  * Adds @timeline to the list of playing timelines held by the master | ||||
|  * clock. | ||||
|  */ | ||||
| void | ||||
| _clutter_master_clock_add_timeline (ClutterMasterClock *master_clock, | ||||
|                                     ClutterTimeline    *timeline) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); | ||||
|  | ||||
|   CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->add_timeline (master_clock, | ||||
|                                                                timeline); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * _clutter_master_clock_remove_timeline: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * | ||||
|  * Removes @timeline from the list of playing timelines held by the | ||||
|  * master clock. | ||||
|  */ | ||||
| void | ||||
| _clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock, | ||||
|                                        ClutterTimeline    *timeline) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); | ||||
|  | ||||
|   CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->remove_timeline (master_clock, | ||||
|                                                                   timeline); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * _clutter_master_clock_start_running: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * | ||||
|  * Called when we have events or redraws to process; if the clock | ||||
|  * is stopped, does the processing necessary to wake it up again. | ||||
|  */ | ||||
| void | ||||
| _clutter_master_clock_start_running (ClutterMasterClock *master_clock) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); | ||||
|  | ||||
|   CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->start_running (master_clock); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * _clutter_master_clock_ensure_next_iteration: | ||||
|  * @master_clock: a #ClutterMasterClock | ||||
|  * | ||||
|  * Ensures that the master clock will run at least one iteration | ||||
|  */ | ||||
| void | ||||
| _clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); | ||||
|  | ||||
|   CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->ensure_next_iteration (master_clock); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_master_clock_set_paused (ClutterMasterClock *master_clock, | ||||
|                                   gboolean            paused) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock)); | ||||
|  | ||||
|   CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->set_paused (master_clock, | ||||
|                                                              !!paused); | ||||
| } | ||||
							
								
								
									
										69
									
								
								clutter/clutter/clutter-master-clock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								clutter/clutter/clutter-master-clock.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  * Copyright (C) 2009  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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_MASTER_CLOCK_H__ | ||||
| #define __CLUTTER_MASTER_CLOCK_H__ | ||||
|  | ||||
| #include <clutter/clutter-timeline.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_MASTER_CLOCK (clutter_master_clock_get_type ()) | ||||
| G_DECLARE_INTERFACE (ClutterMasterClock, clutter_master_clock, | ||||
|                      CLUTTER, MASTER_CLOCK, | ||||
|                      GObject) | ||||
|  | ||||
| struct _ClutterMasterClockInterface | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GTypeInterface parent_iface; | ||||
|  | ||||
|   void (* add_timeline)           (ClutterMasterClock *master_clock, | ||||
|                                    ClutterTimeline    *timeline); | ||||
|   void (* remove_timeline)        (ClutterMasterClock *master_clock, | ||||
|                                    ClutterTimeline    *timeline); | ||||
|   void (* start_running)          (ClutterMasterClock *master_clock); | ||||
|   void (* ensure_next_iteration)  (ClutterMasterClock *master_clock); | ||||
|   void (* set_paused)             (ClutterMasterClock *master_clock, | ||||
|                                    gboolean            paused); | ||||
| }; | ||||
|  | ||||
| ClutterMasterClock *    _clutter_master_clock_get_default               (void); | ||||
| void                    _clutter_master_clock_add_timeline              (ClutterMasterClock *master_clock, | ||||
|                                                                          ClutterTimeline    *timeline); | ||||
| void                    _clutter_master_clock_remove_timeline           (ClutterMasterClock *master_clock, | ||||
|                                                                          ClutterTimeline    *timeline); | ||||
| void                    _clutter_master_clock_start_running             (ClutterMasterClock *master_clock); | ||||
| void                    _clutter_master_clock_ensure_next_iteration     (ClutterMasterClock *master_clock); | ||||
| void                    _clutter_master_clock_set_paused                (ClutterMasterClock *master_clock, | ||||
|                                                                          gboolean            paused); | ||||
|  | ||||
| void                    _clutter_timeline_advance                       (ClutterTimeline    *timeline, | ||||
|                                                                          gint64              tick_time); | ||||
| gint64                  _clutter_timeline_get_delta                     (ClutterTimeline    *timeline); | ||||
| void                    _clutter_timeline_do_tick                       (ClutterTimeline    *timeline, | ||||
|                                                                          gint64              tick_time); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_MASTER_CLOCK_H__ */ | ||||
| @@ -39,10 +39,6 @@ | ||||
| CLUTTER_EXPORT | ||||
| GList * clutter_stage_peek_stage_views (ClutterStage *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean clutter_actor_is_effectively_on_stage_view (ClutterActor     *self, | ||||
|                                                      ClutterStageView *view); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_set_custom_backend_func (ClutterBackend *(* func) (void)); | ||||
|  | ||||
| @@ -73,7 +69,13 @@ gboolean clutter_stage_paint_to_buffer (ClutterStage                 *stage, | ||||
|                                         GError                      **error); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_clear_stage_views (ClutterStage *stage); | ||||
| void clutter_stage_freeze_updates (ClutterStage *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_thaw_updates (ClutterStage *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_update_resource_scales (ClutterStage *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_view_assign_next_scanout (ClutterStageView *stage_view, | ||||
|   | ||||
| @@ -60,30 +60,6 @@ | ||||
|  * #ClutterOffscreenEffectClass.create_texture() virtual function; no chain up | ||||
|  * to the #ClutterOffscreenEffect implementation is required in this | ||||
|  * case. | ||||
|  * | ||||
|  * ## Paint nodes | ||||
|  * | ||||
|  * #ClutterOffscreenEffect is generates the following paint node tree: | ||||
|  * | ||||
|  * |[<!-- language="plain" --> | ||||
|  * Effect | ||||
|  *  ├─────────┐ | ||||
|  * Layer   Pipeline | ||||
|  *  │ | ||||
|  * Actor | ||||
|  * ]| | ||||
|  * | ||||
|  * When the actor contents are cached, the generated paint node tree | ||||
|  * looks like this: | ||||
|  * | ||||
|  * |[<!-- language="plain" --> | ||||
|  * Effect | ||||
|  *  │ | ||||
|  * Pipeline | ||||
|  * ]| | ||||
|  * | ||||
|  * In both cases, the "Pipeline" node is created with the return value | ||||
|  * of #ClutterOffscreenEffectClass.create_pipeline(). | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
| @@ -99,8 +75,6 @@ | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-stage-private.h" | ||||
| #include "clutter-paint-context-private.h" | ||||
| #include "clutter-paint-node-private.h" | ||||
| #include "clutter-paint-nodes.h" | ||||
| #include "clutter-paint-volume-private.h" | ||||
| #include "clutter-actor-box-private.h" | ||||
|  | ||||
| @@ -113,6 +87,8 @@ struct _ClutterOffscreenEffectPrivate | ||||
|   ClutterActor *actor; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   graphene_point3d_t position; | ||||
|  | ||||
|   int fbo_offset_x; | ||||
|   int fbo_offset_y; | ||||
|  | ||||
| @@ -182,25 +158,6 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self, | ||||
|                                    filter, filter); | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_offscreen_effect_real_create_pipeline (ClutterOffscreenEffect *effect, | ||||
|                                                CoglTexture            *texture) | ||||
| { | ||||
|   ClutterOffscreenEffectPrivate *priv = effect->priv; | ||||
|   CoglContext *ctx = | ||||
|     clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   CoglPipeline *pipeline; | ||||
|   float resource_scale; | ||||
|  | ||||
|   resource_scale = clutter_actor_get_real_resource_scale (priv->actor); | ||||
|  | ||||
|   pipeline = cogl_pipeline_new (ctx); | ||||
|   ensure_pipeline_filter_for_scale (effect, resource_scale); | ||||
|   cogl_pipeline_set_layer_texture (pipeline, 0, texture); | ||||
|  | ||||
|   return pipeline; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| update_fbo (ClutterEffect *effect, | ||||
|             int            target_width, | ||||
| @@ -209,8 +166,6 @@ update_fbo (ClutterEffect *effect, | ||||
| { | ||||
|   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|   ClutterOffscreenEffectPrivate *priv = self->priv; | ||||
|   ClutterOffscreenEffectClass *offscreen_class = | ||||
|     CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect); | ||||
|  | ||||
|   priv->stage = clutter_actor_get_stage (priv->actor); | ||||
|   if (priv->stage == NULL) | ||||
| @@ -230,6 +185,15 @@ update_fbo (ClutterEffect *effect, | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
|   if (priv->pipeline == NULL) | ||||
|     { | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|       priv->pipeline = cogl_pipeline_new (ctx); | ||||
|       ensure_pipeline_filter_for_scale (self, resource_scale); | ||||
|     } | ||||
|  | ||||
|   g_clear_pointer (&priv->texture, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|  | ||||
| @@ -238,6 +202,8 @@ update_fbo (ClutterEffect *effect, | ||||
|   if (priv->texture == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture); | ||||
|  | ||||
|   priv->target_width = target_width; | ||||
|   priv->target_height = target_height; | ||||
|  | ||||
| @@ -246,7 +212,8 @@ update_fbo (ClutterEffect *effect, | ||||
|     { | ||||
|       g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC); | ||||
|  | ||||
|       cogl_clear_object (&priv->pipeline); | ||||
|       cogl_object_unref (priv->pipeline); | ||||
|       priv->pipeline = NULL; | ||||
|  | ||||
|       priv->target_width = 0; | ||||
|       priv->target_height = 0; | ||||
| @@ -254,42 +221,50 @@ update_fbo (ClutterEffect *effect, | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   cogl_clear_object (&priv->pipeline); | ||||
|   priv->pipeline = offscreen_class->create_pipeline (self, priv->texture); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_offscreen_effect_pre_paint (ClutterEffect       *effect, | ||||
|                                     ClutterPaintNode    *node, | ||||
|                                     ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|   ClutterOffscreenEffectPrivate *priv = self->priv; | ||||
|   ClutterActorBox raw_box, box; | ||||
|   ClutterActor *stage; | ||||
|   CoglMatrix projection, modelview; | ||||
|   CoglMatrix projection, old_modelview, modelview; | ||||
|   const ClutterPaintVolume *volume; | ||||
|   CoglColor transparent; | ||||
|   gfloat stage_width, stage_height; | ||||
|   gfloat target_width = -1, target_height = -1; | ||||
|   float resource_scale; | ||||
|   float ceiled_resource_scale; | ||||
|   CoglFramebuffer *framebuffer; | ||||
|   gfloat resource_scale; | ||||
|   gfloat ceiled_resource_scale; | ||||
|   graphene_point3d_t local_offset; | ||||
|   gfloat old_viewport[4]; | ||||
|  | ||||
|   local_offset = GRAPHENE_POINT3D_INIT (0.0f, 0.0f, 0.0f); | ||||
|  | ||||
|   if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) | ||||
|     goto fail; | ||||
|     return FALSE; | ||||
|  | ||||
|   if (priv->actor == NULL) | ||||
|     goto fail; | ||||
|     return FALSE; | ||||
|  | ||||
|   stage = _clutter_actor_get_stage_internal (priv->actor); | ||||
|   clutter_actor_get_size (stage, &stage_width, &stage_height); | ||||
|  | ||||
|   resource_scale = clutter_actor_get_real_resource_scale (priv->actor); | ||||
|  | ||||
|   ceiled_resource_scale = ceilf (resource_scale); | ||||
|   stage_width *= ceiled_resource_scale; | ||||
|   stage_height *= ceiled_resource_scale; | ||||
|   if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale)) | ||||
|     { | ||||
|       ceiled_resource_scale = ceilf (resource_scale); | ||||
|       stage_width *= ceiled_resource_scale; | ||||
|       stage_height *= ceiled_resource_scale; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* We are sure we have a resource scale set to a good value at paint */ | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
|  | ||||
|   /* Get the minimal bounding box for what we want to paint, relative to the | ||||
|    * parent of priv->actor. Note that we may actually be painting a clone of | ||||
| @@ -325,7 +300,12 @@ clutter_offscreen_effect_pre_paint (ClutterEffect       *effect, | ||||
|  | ||||
|   /* First assert that the framebuffer is the right size... */ | ||||
|   if (!update_fbo (effect, target_width, target_height, resource_scale)) | ||||
|     goto fail; | ||||
|     return FALSE; | ||||
|  | ||||
|   framebuffer = clutter_paint_context_get_framebuffer (paint_context); | ||||
|   cogl_framebuffer_get_modelview_matrix (framebuffer, &old_modelview); | ||||
|  | ||||
|   clutter_paint_context_push_framebuffer (paint_context, priv->offscreen); | ||||
|  | ||||
|   /* We don't want the FBO contents to be transformed. That could waste memory | ||||
|    * (e.g. during zoom), or result in something that's not rectangular (clipped | ||||
| @@ -337,6 +317,13 @@ clutter_offscreen_effect_pre_paint (ClutterEffect       *effect, | ||||
|   clutter_actor_get_transform (priv->stage, &modelview); | ||||
|   cogl_framebuffer_set_modelview_matrix (priv->offscreen, &modelview); | ||||
|  | ||||
|   /* Save the original viewport for calculating priv->position */ | ||||
|   _clutter_stage_get_viewport (CLUTTER_STAGE (priv->stage), | ||||
|                                &old_viewport[0], | ||||
|                                &old_viewport[1], | ||||
|                                &old_viewport[2], | ||||
|                                &old_viewport[3]); | ||||
|  | ||||
|   /* Set up the viewport so that it has the same size as the stage (avoid | ||||
|    * distortion), but translated to account for the FBO offset... | ||||
|    */ | ||||
| @@ -350,22 +337,45 @@ clutter_offscreen_effect_pre_paint (ClutterEffect       *effect, | ||||
|   _clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage), | ||||
|                                         &projection); | ||||
|  | ||||
|   /* Now save the global position of the effect (not just of the actor). | ||||
|    * It doesn't appear anyone actually uses this yet, but get_target_rect is | ||||
|    * documented as returning it. So we should... | ||||
|    */ | ||||
|   _clutter_util_fully_transform_vertices (&old_modelview, | ||||
|                                           &projection, | ||||
|                                           old_viewport, | ||||
|                                           &local_offset, | ||||
|                                           &priv->position, | ||||
|                                           1); | ||||
|  | ||||
|   cogl_framebuffer_set_projection_matrix (priv->offscreen, &projection); | ||||
|  | ||||
|   return TRUE; | ||||
|   cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0); | ||||
|   cogl_framebuffer_clear (priv->offscreen, | ||||
|                           COGL_BUFFER_BIT_COLOR | | ||||
|                           COGL_BUFFER_BIT_DEPTH, | ||||
|                           &transparent); | ||||
|  | ||||
| fail: | ||||
|   cogl_clear_object (&priv->offscreen); | ||||
|   return FALSE; | ||||
|   cogl_framebuffer_push_matrix (priv->offscreen); | ||||
|  | ||||
|   /* Override the actor's opacity to fully opaque - we paint the offscreen | ||||
|    * texture with the actor's paint opacity, so we need to do this to avoid | ||||
|    * multiplying the opacity twice. | ||||
|    */ | ||||
|   priv->old_opacity_override = | ||||
|     clutter_actor_get_opacity_override (priv->actor); | ||||
|   clutter_actor_set_opacity_override (priv->actor, 0xff); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                             ClutterPaintNode       *node, | ||||
|                                             ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterOffscreenEffectPrivate *priv = effect->priv; | ||||
|   ClutterPaintNode *pipeline_node; | ||||
|   CoglFramebuffer *framebuffer = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|   guint8 paint_opacity; | ||||
|  | ||||
|   paint_opacity = clutter_actor_get_paint_opacity (priv->actor); | ||||
| @@ -376,122 +386,95 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect, | ||||
|                               paint_opacity, | ||||
|                               paint_opacity); | ||||
|  | ||||
|   pipeline_node = clutter_pipeline_node_new (priv->pipeline); | ||||
|   clutter_paint_node_set_static_name (pipeline_node, | ||||
|                                       "ClutterOffscreenEffect (pipeline)"); | ||||
|   clutter_paint_node_add_child (node, pipeline_node); | ||||
|  | ||||
|   /* At this point we are in stage coordinates translated so if | ||||
|    * we draw our texture using a textured quad the size of the paint | ||||
|    * box then we will overlay where the actor would have drawn if it | ||||
|    * hadn't been redirected offscreen. | ||||
|    */ | ||||
|   clutter_paint_node_add_rectangle (pipeline_node, | ||||
|                                     &(ClutterActorBox) { | ||||
|                                         0.f, 0.f, | ||||
|                                         cogl_texture_get_width (priv->texture), | ||||
|                                         cogl_texture_get_height (priv->texture), | ||||
|                                     }); | ||||
|  | ||||
|   clutter_paint_node_unref (pipeline_node); | ||||
|   cogl_framebuffer_draw_textured_rectangle (framebuffer, | ||||
|                                             priv->pipeline, | ||||
|                                             0, 0, | ||||
|                                             cogl_texture_get_width (priv->texture), | ||||
|                                             cogl_texture_get_height (priv->texture), | ||||
|                                             0.0, 0.0, | ||||
|                                             1.0, 1.0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect, | ||||
|                                         ClutterPaintNode       *node, | ||||
|                                         ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterOffscreenEffectPrivate *priv = effect->priv; | ||||
|   CoglMatrix transform; | ||||
|   CoglFramebuffer *framebuffer = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|   CoglMatrix modelview; | ||||
|   float resource_scale; | ||||
|  | ||||
|   cogl_matrix_init_identity (&transform); | ||||
|   cogl_framebuffer_push_matrix (framebuffer); | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (priv->actor); | ||||
|   /* The current modelview matrix is *almost* perfect already. It's only | ||||
|    * missing a correction for the expanded FBO and offset rendering within... | ||||
|    */ | ||||
|   cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview); | ||||
|  | ||||
|   if (resource_scale != 1.0f) | ||||
|   if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) && | ||||
|       resource_scale != 1.0f) | ||||
|     { | ||||
|       float paint_scale = 1.0f / resource_scale; | ||||
|       cogl_matrix_scale (&transform, paint_scale, paint_scale, 1); | ||||
|       cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1); | ||||
|     } | ||||
|  | ||||
|   cogl_matrix_translate (&transform, | ||||
|   cogl_matrix_translate (&modelview, | ||||
|                          priv->fbo_offset_x, | ||||
|                          priv->fbo_offset_y, | ||||
|                          0.0f); | ||||
|  | ||||
|   if (!cogl_matrix_is_identity (&transform)) | ||||
|     { | ||||
|       ClutterPaintNode *transform_node; | ||||
|  | ||||
|       transform_node = clutter_transform_node_new (&transform); | ||||
|       clutter_paint_node_set_static_name (transform_node, | ||||
|                                           "ClutterOffscreenEffect (transform)"); | ||||
|       clutter_paint_node_add_child (node, transform_node); | ||||
|       clutter_paint_node_unref (transform_node); | ||||
|  | ||||
|       node = transform_node; | ||||
|     } | ||||
|   cogl_framebuffer_set_modelview_matrix (framebuffer, &modelview); | ||||
|  | ||||
|   /* paint the target material; this is virtualized for | ||||
|    * sub-classes that require special hand-holding | ||||
|    */ | ||||
|   clutter_offscreen_effect_paint_target (effect, node, paint_context); | ||||
|   clutter_offscreen_effect_paint_target (effect, paint_context); | ||||
|  | ||||
|   cogl_framebuffer_pop_matrix (framebuffer); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_post_paint (ClutterEffect       *effect, | ||||
|                                      ClutterPaintNode    *node, | ||||
|                                      ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|   ClutterOffscreenEffectPrivate *priv = self->priv; | ||||
|   CoglFramebuffer *framebuffer; | ||||
|  | ||||
|   g_warn_if_fail (priv->offscreen); | ||||
|   g_warn_if_fail (priv->pipeline); | ||||
|   g_warn_if_fail (priv->actor); | ||||
|  | ||||
|   clutter_offscreen_effect_paint_texture (self, node, paint_context); | ||||
| } | ||||
|   /* Restore the previous opacity override */ | ||||
|   if (priv->actor) | ||||
|     { | ||||
|       clutter_actor_set_opacity_override (priv->actor, | ||||
|                                           priv->old_opacity_override); | ||||
|     } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_paint_node (ClutterEffect           *effect, | ||||
|                                      ClutterPaintNode        *node, | ||||
|                                      ClutterPaintContext     *paint_context, | ||||
|                                      ClutterEffectPaintFlags  flags) | ||||
| { | ||||
|   ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|   ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv; | ||||
|   ClutterPaintNode *layer_node; | ||||
|   ClutterPaintNode *actor_node; | ||||
|   framebuffer = clutter_paint_context_get_framebuffer (paint_context); | ||||
|   cogl_framebuffer_pop_matrix (framebuffer); | ||||
|   clutter_paint_context_pop_framebuffer (paint_context); | ||||
|  | ||||
|   layer_node = clutter_layer_node_new_with_framebuffer (priv->offscreen, | ||||
|                                                         priv->pipeline, | ||||
|                                                         255); | ||||
|   clutter_paint_node_set_static_name (layer_node, | ||||
|                                       "ClutterOffscreenEffect (actor offscreen)"); | ||||
|   clutter_paint_node_add_child (node, layer_node); | ||||
|   clutter_paint_node_unref (layer_node); | ||||
|  | ||||
|   actor_node = clutter_actor_node_new (priv->actor, 255); | ||||
|   clutter_paint_node_add_child (layer_node, actor_node); | ||||
|   clutter_paint_node_unref (actor_node); | ||||
|   clutter_offscreen_effect_paint_texture (self, paint_context); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_offscreen_effect_paint (ClutterEffect           *effect, | ||||
|                                 ClutterPaintNode        *node, | ||||
|                                 ClutterPaintContext     *paint_context, | ||||
|                                 ClutterEffectPaintFlags  flags) | ||||
| { | ||||
|   ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); | ||||
|   ClutterOffscreenEffectPrivate *priv = self->priv; | ||||
|   ClutterEffectClass *parent_class = | ||||
|     CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class); | ||||
|  | ||||
|   if (flags & CLUTTER_EFFECT_PAINT_BYPASS_EFFECT) | ||||
|     { | ||||
|       parent_class->paint_node (effect, node, paint_context, flags); | ||||
|       clutter_actor_continue_paint (priv->actor, paint_context); | ||||
|       cogl_clear_object (&priv->offscreen); | ||||
|       return; | ||||
|     } | ||||
| @@ -500,9 +483,21 @@ clutter_offscreen_effect_paint (ClutterEffect           *effect, | ||||
|    * then we can just use the cached image in the FBO. | ||||
|    */ | ||||
|   if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY)) | ||||
|     parent_class->paint (effect, node, paint_context, flags); | ||||
|     { | ||||
|       ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect); | ||||
|       gboolean pre_paint_succeeded; | ||||
|  | ||||
|       pre_paint_succeeded = effect_class->pre_paint (effect, paint_context); | ||||
|  | ||||
|       clutter_actor_continue_paint (priv->actor, paint_context); | ||||
|  | ||||
|       if (pre_paint_succeeded) | ||||
|         effect_class->post_paint (effect, paint_context); | ||||
|       else | ||||
|         g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|     } | ||||
|   else | ||||
|     clutter_offscreen_effect_paint_texture (self, node, paint_context); | ||||
|     clutter_offscreen_effect_paint_texture (self, paint_context); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -540,7 +535,6 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass) | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   klass->create_texture = clutter_offscreen_effect_real_create_texture; | ||||
|   klass->create_pipeline = clutter_offscreen_effect_real_create_pipeline; | ||||
|   klass->paint_target = clutter_offscreen_effect_real_paint_target; | ||||
|  | ||||
|   meta_class->set_actor = clutter_offscreen_effect_set_actor; | ||||
| @@ -549,7 +543,6 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass) | ||||
|   effect_class->pre_paint = clutter_offscreen_effect_pre_paint; | ||||
|   effect_class->post_paint = clutter_offscreen_effect_post_paint; | ||||
|   effect_class->paint = clutter_offscreen_effect_paint; | ||||
|   effect_class->paint_node = clutter_offscreen_effect_paint_node; | ||||
|  | ||||
|   gobject_class->finalize = clutter_offscreen_effect_finalize; | ||||
| } | ||||
| @@ -590,34 +583,33 @@ clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_offscreen_effect_get_pipeline: | ||||
|  * clutter_offscreen_effect_get_target: (skip) | ||||
|  * @effect: a #ClutterOffscreenEffect | ||||
|  * | ||||
|  * Retrieves the pipeline used as a render target for the offscreen | ||||
|  * Retrieves the material used as a render target for the offscreen | ||||
|  * buffer created by @effect | ||||
|  * | ||||
|  * You should only use the returned #CoglPipeline when painting. The | ||||
|  * returned pipeline might change between different frames. | ||||
|  * You should only use the returned #CoglMaterial when painting. The | ||||
|  * returned material might change between different frames. | ||||
|  * | ||||
|  * Return value: (transfer none)(nullable): a #CoglPipeline. The | ||||
|  *   pipeline is owned by Clutter and it should not be modified | ||||
|  *   or freed | ||||
|  * Return value: (transfer none): a #CoglMaterial or %NULL. The | ||||
|  *   returned material is owned by Clutter and it should not be | ||||
|  *   modified or freed | ||||
|  * | ||||
|  * Since: 1.4 | ||||
|  */ | ||||
| CoglPipeline * | ||||
| clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect) | ||||
| CoglMaterial * | ||||
| clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), | ||||
|                         NULL); | ||||
|  | ||||
|   return effect->priv->pipeline; | ||||
|   return (CoglMaterial *)effect->priv->pipeline; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_offscreen_effect_paint_target: | ||||
|  * @effect: a #ClutterOffscreenEffect | ||||
|  * @node: a #ClutterPaintNode | ||||
|  * @paint_context: a #ClutterPaintContext | ||||
|  * | ||||
|  * Calls the paint_target() virtual function of the @effect | ||||
| @@ -626,13 +618,11 @@ clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect) | ||||
|  */ | ||||
| void | ||||
| clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                        ClutterPaintNode       *node, | ||||
|                                        ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect)); | ||||
|  | ||||
|   CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect, | ||||
|                                                              node, | ||||
|                                                              paint_context); | ||||
| } | ||||
|  | ||||
| @@ -680,6 +670,8 @@ clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect, | ||||
|  *   and %FALSE otherwise | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  * | ||||
|  * Deprecated: 1.14: Use clutter_offscreen_effect_get_target_rect() instead | ||||
|  */ | ||||
| gboolean | ||||
| clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect, | ||||
| @@ -703,3 +695,43 @@ clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect, | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_offscreen_effect_get_target_rect: | ||||
|  * @effect: a #ClutterOffscreenEffect | ||||
|  * @rect: (out caller-allocates): return location for the target area | ||||
|  * | ||||
|  * Retrieves the origin and size of the offscreen buffer used by @effect to | ||||
|  * paint the actor to which it has been applied. | ||||
|  * | ||||
|  * This function should only be called by #ClutterOffscreenEffect | ||||
|  * implementations, from within the #ClutterOffscreenEffectClass.paint_target() | ||||
|  * virtual function. | ||||
|  * | ||||
|  * Return value: %TRUE if the offscreen buffer has a valid rectangle, | ||||
|  *   and %FALSE otherwise | ||||
|  * | ||||
|  * Since: 1.14 | ||||
|  */ | ||||
| gboolean | ||||
| clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect, | ||||
|                                           graphene_rect_t        *rect) | ||||
| { | ||||
|   ClutterOffscreenEffectPrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), FALSE); | ||||
|   g_return_val_if_fail (rect != NULL, FALSE); | ||||
|  | ||||
|   priv = effect->priv; | ||||
|  | ||||
|   if (priv->texture == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   graphene_rect_init (rect, | ||||
|                       priv->position.x, | ||||
|                       priv->position.y, | ||||
|                       cogl_texture_get_width (priv->texture), | ||||
|                       cogl_texture_get_height (priv->texture)); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -79,10 +79,7 @@ struct _ClutterOffscreenEffectClass | ||||
|   CoglHandle (* create_texture) (ClutterOffscreenEffect *effect, | ||||
|                                  gfloat                  width, | ||||
|                                  gfloat                  height); | ||||
|   CoglPipeline* (* create_pipeline) (ClutterOffscreenEffect *effect, | ||||
|                                      CoglTexture            *texture); | ||||
|   void       (* paint_target)   (ClutterOffscreenEffect *effect, | ||||
|                                  ClutterPaintNode       *node, | ||||
|                                  ClutterPaintContext    *paint_context); | ||||
|  | ||||
|   /*< private >*/ | ||||
| @@ -99,25 +96,28 @@ CLUTTER_EXPORT | ||||
| GType clutter_offscreen_effect_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| CoglPipeline *  clutter_offscreen_effect_get_pipeline           (ClutterOffscreenEffect *effect); | ||||
| CoglMaterial *  clutter_offscreen_effect_get_target             (ClutterOffscreenEffect *effect); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| CoglHandle      clutter_offscreen_effect_get_texture            (ClutterOffscreenEffect *effect); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_offscreen_effect_paint_target           (ClutterOffscreenEffect *effect, | ||||
|                                                                  ClutterPaintNode       *node, | ||||
|                                                                  ClutterPaintContext    *paint_context); | ||||
| CLUTTER_EXPORT | ||||
| CoglHandle      clutter_offscreen_effect_create_texture         (ClutterOffscreenEffect *effect, | ||||
|                                                                  gfloat                  width, | ||||
|                                                                  gfloat                  height); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| CLUTTER_DEPRECATED_FOR (clutter_offscreen_effect_get_target_rect) | ||||
| gboolean        clutter_offscreen_effect_get_target_size        (ClutterOffscreenEffect *effect, | ||||
|                                                                  gfloat                 *width, | ||||
|                                                                  gfloat                 *height); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_offscreen_effect_get_target_rect        (ClutterOffscreenEffect *effect, | ||||
|                                                                  graphene_rect_t        *rect); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_OFFSCREEN_EFFECT_H__ */ | ||||
|   | ||||
| @@ -141,26 +141,6 @@ ClutterPaintNode *      clutter_paint_node_get_last_child               (Clutter | ||||
| G_GNUC_INTERNAL | ||||
| ClutterPaintNode *      clutter_paint_node_get_parent                   (ClutterPaintNode      *node); | ||||
|  | ||||
|  | ||||
| #define CLUTTER_TYPE_EFFECT_NODE                (clutter_effect_node_get_type ()) | ||||
| #define CLUTTER_EFFECT_NODE(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EFFECT_NODE, ClutterEffectNode)) | ||||
| #define CLUTTER_IS_EFFECT_NODE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EFFECT_NODE)) | ||||
|  | ||||
| /** | ||||
|  * ClutterEffectNode: | ||||
|  * | ||||
|  * The #ClutterEffectNode structure is an opaque | ||||
|  * type whose members cannot be directly accessed. | ||||
|  */ | ||||
| typedef struct _ClutterEffectNode ClutterEffectNode; | ||||
| typedef struct _ClutterEffectNode ClutterEffectNodeClass; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_effect_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode * clutter_effect_node_new (ClutterEffect *actor); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -551,7 +551,7 @@ clutter_pipeline_node_init (ClutterPipelineNode *self) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_pipeline_node_new: | ||||
|  * clutter_pipeline_node_new: (skip) | ||||
|  * @pipeline: (allow-none): a Cogl pipeline state object, or %NULL | ||||
|  * | ||||
|  * Creates a new #ClutterPaintNode that will use the @pipeline to | ||||
| @@ -1115,8 +1115,6 @@ struct _ClutterActorNode | ||||
|   ClutterPaintNode parent_instance; | ||||
|  | ||||
|   ClutterActor *actor; | ||||
|   int opacity_override; | ||||
|   int old_opacity_override; | ||||
| }; | ||||
|  | ||||
| struct _ClutterActorNodeClass | ||||
| @@ -1132,14 +1130,6 @@ clutter_actor_node_pre_draw (ClutterPaintNode    *node, | ||||
| { | ||||
|   ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node); | ||||
|  | ||||
|   if (actor_node->opacity_override != -1) | ||||
|     { | ||||
|       actor_node->old_opacity_override = | ||||
|         clutter_actor_get_opacity_override (actor_node->actor); | ||||
|       clutter_actor_set_opacity_override (actor_node->actor, | ||||
|                                           actor_node->opacity_override); | ||||
|     } | ||||
|  | ||||
|   CLUTTER_SET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT); | ||||
|  | ||||
|   return TRUE; | ||||
| @@ -1161,12 +1151,6 @@ clutter_actor_node_post_draw (ClutterPaintNode    *node, | ||||
|   ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node); | ||||
|  | ||||
|   CLUTTER_UNSET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT); | ||||
|  | ||||
|  if (actor_node->opacity_override != -1) | ||||
|     { | ||||
|       clutter_actor_set_opacity_override (actor_node->actor, | ||||
|                                           actor_node->old_opacity_override); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static JsonNode * | ||||
| @@ -1208,7 +1192,6 @@ clutter_actor_node_init (ClutterActorNode *self) | ||||
| /* | ||||
|  * clutter_actor_node_new: | ||||
|  * @actor: the actor to paint | ||||
|  * @opacity: opacity to draw the actor with, or -1 to use the actor's opacity | ||||
|  * | ||||
|  * Creates a new #ClutterActorNode. | ||||
|  * | ||||
| @@ -1220,8 +1203,7 @@ clutter_actor_node_init (ClutterActorNode *self) | ||||
|  *   Use clutter_paint_node_unref() when done. | ||||
|  */ | ||||
| ClutterPaintNode * | ||||
| clutter_actor_node_new (ClutterActor *actor, | ||||
|                         int           opacity) | ||||
| clutter_actor_node_new (ClutterActor *actor) | ||||
| { | ||||
|   ClutterActorNode *res; | ||||
|  | ||||
| @@ -1229,96 +1211,11 @@ clutter_actor_node_new (ClutterActor *actor, | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_ACTOR_NODE); | ||||
|   res->actor = actor; | ||||
|   res->opacity_override = CLAMP (opacity, -1, 255); | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * ClutterEffectNode | ||||
|  */ | ||||
|  | ||||
| struct _ClutterEffectNode | ||||
| { | ||||
|   ClutterPaintNode parent_instance; | ||||
|  | ||||
|   ClutterEffect *effect; | ||||
| }; | ||||
|  | ||||
| struct _ClutterEffectNodeClass | ||||
| { | ||||
|   ClutterPaintNodeClass parent_class; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (ClutterEffectNode, clutter_effect_node, CLUTTER_TYPE_PAINT_NODE) | ||||
|  | ||||
| static JsonNode * | ||||
| clutter_effect_node_serialize (ClutterPaintNode *node) | ||||
| { | ||||
|   ClutterEffectNode *effect_node = CLUTTER_EFFECT_NODE (node); | ||||
|   ClutterActorMeta *effect_meta = CLUTTER_ACTOR_META (effect_node->effect); | ||||
|   g_autoptr (JsonBuilder) builder = NULL; | ||||
|   g_autoptr (GString) string = NULL; | ||||
|   const char *meta_name; | ||||
|  | ||||
|   meta_name = clutter_actor_meta_get_name (effect_meta); | ||||
|  | ||||
|   string = g_string_new (NULL); | ||||
|   g_string_append (string, G_OBJECT_TYPE_NAME (effect_node->effect)); | ||||
|   g_string_append (string, " ("); | ||||
|   if (meta_name) | ||||
|     g_string_append_printf (string, "\"%s\"", meta_name); | ||||
|   else | ||||
|     g_string_append (string, "unnamed"); | ||||
|   g_string_append (string, ")"); | ||||
|  | ||||
|   builder = json_builder_new (); | ||||
|  | ||||
|   json_builder_begin_object (builder); | ||||
|   json_builder_set_member_name (builder, "effect"); | ||||
|   json_builder_add_string_value (builder, string->str); | ||||
|   json_builder_end_object (builder); | ||||
|  | ||||
|   return json_builder_get_root (builder); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_node_class_init (ClutterEffectNodeClass *klass) | ||||
| { | ||||
|   ClutterPaintNodeClass *node_class; | ||||
|  | ||||
|   node_class = CLUTTER_PAINT_NODE_CLASS (klass); | ||||
|   node_class->serialize = clutter_effect_node_serialize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_effect_node_init (ClutterEffectNode *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * clutter_effect_node_new: | ||||
|  * @actor: the actor to paint | ||||
|  * | ||||
|  * Creates a new #ClutterEffectNode. | ||||
|  * | ||||
|  * Return value: (transfer full): the newly created #ClutterEffectNode. | ||||
|  *   Use clutter_paint_node_unref() when done. | ||||
|  */ | ||||
| ClutterPaintNode * | ||||
| clutter_effect_node_new (ClutterEffect *effect) | ||||
| { | ||||
|   ClutterEffectNode *res; | ||||
|  | ||||
|   g_assert (effect != NULL); | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_EFFECT_NODE); | ||||
|   res->effect = effect; | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * ClutterLayerNode | ||||
|  */ | ||||
| @@ -1338,7 +1235,6 @@ struct _ClutterLayerNode | ||||
|   CoglFramebuffer *offscreen; | ||||
|  | ||||
|   guint8 opacity; | ||||
|   gboolean update_modelview; | ||||
| }; | ||||
|  | ||||
| struct _ClutterLayerNodeClass | ||||
| @@ -1353,6 +1249,8 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node, | ||||
|                              ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterLayerNode *lnode = (ClutterLayerNode *) node; | ||||
|   CoglFramebuffer *framebuffer; | ||||
|   CoglMatrix matrix; | ||||
|  | ||||
|   /* if we were unable to create an offscreen buffer for this node, then | ||||
|    * we simply ignore it | ||||
| @@ -1360,30 +1258,29 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node, | ||||
|   if (lnode->offscreen == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (lnode->update_modelview) | ||||
|     { | ||||
|       CoglFramebuffer *framebuffer; | ||||
|       CoglMatrix matrix; | ||||
|   /* if no geometry was submitted for this node then we simply ignore it */ | ||||
|   if (node->operations == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|       /* copy the same modelview from the current framebuffer to the one we | ||||
|        * are going to use | ||||
|        */ | ||||
|       framebuffer = clutter_paint_context_get_framebuffer (paint_context); | ||||
|       cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix); | ||||
|       cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix); | ||||
|  | ||||
|       cogl_framebuffer_set_viewport (lnode->offscreen, | ||||
|                                      lnode->viewport.x, | ||||
|                                      lnode->viewport.y, | ||||
|                                      lnode->viewport.width, | ||||
|                                      lnode->viewport.height); | ||||
|  | ||||
|       cogl_framebuffer_set_projection_matrix (lnode->offscreen, | ||||
|                                               &lnode->projection); | ||||
|     } | ||||
|   /* copy the same modelview from the current framebuffer to the one we | ||||
|    * are going to use | ||||
|    */ | ||||
|   framebuffer = clutter_paint_context_get_framebuffer (paint_context); | ||||
|   cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix); | ||||
|  | ||||
|   clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen); | ||||
|  | ||||
|   cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix); | ||||
|  | ||||
|   cogl_framebuffer_set_viewport (lnode->offscreen, | ||||
|                                  lnode->viewport.x, | ||||
|                                  lnode->viewport.y, | ||||
|                                  lnode->viewport.width, | ||||
|                                  lnode->viewport.height); | ||||
|  | ||||
|   cogl_framebuffer_set_projection_matrix (lnode->offscreen, | ||||
|                                           &lnode->projection); | ||||
|  | ||||
|   /* clear out the target framebuffer */ | ||||
|   cogl_framebuffer_clear4f (lnode->offscreen, | ||||
|                             COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH, | ||||
| @@ -1410,10 +1307,6 @@ clutter_layer_node_post_draw (ClutterPaintNode    *node, | ||||
|   cogl_framebuffer_pop_matrix (lnode->offscreen); | ||||
|   clutter_paint_context_pop_framebuffer (paint_context); | ||||
|  | ||||
|   /* if no geometry was submitted for this node then we simply ignore it */ | ||||
|   if (node->operations == NULL) | ||||
|     return; | ||||
|  | ||||
|   fb = clutter_paint_context_get_framebuffer (paint_context); | ||||
|  | ||||
|   for (i = 0; i < node->operations->len; i++) | ||||
| @@ -1474,25 +1367,6 @@ clutter_layer_node_finalize (ClutterPaintNode *node) | ||||
|   CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node); | ||||
| } | ||||
|  | ||||
| static JsonNode * | ||||
| clutter_layer_node_serialize (ClutterPaintNode *node) | ||||
| { | ||||
|   ClutterLayerNode *layer_node = CLUTTER_LAYER_NODE (node); | ||||
|   g_autoptr (JsonBuilder) builder = NULL; | ||||
|   g_autofree char *framebuffer_ptr = NULL; | ||||
|  | ||||
|   builder = json_builder_new (); | ||||
|  | ||||
|   framebuffer_ptr = g_strdup_printf ("%p", layer_node->offscreen); | ||||
|  | ||||
|   json_builder_begin_object (builder); | ||||
|   json_builder_set_member_name (builder, "framebuffer"); | ||||
|   json_builder_add_string_value (builder, framebuffer_ptr); | ||||
|   json_builder_end_object (builder); | ||||
|  | ||||
|   return json_builder_get_root (builder); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_layer_node_class_init (ClutterLayerNodeClass *klass) | ||||
| { | ||||
| @@ -1502,7 +1376,6 @@ clutter_layer_node_class_init (ClutterLayerNodeClass *klass) | ||||
|   node_class->pre_draw = clutter_layer_node_pre_draw; | ||||
|   node_class->post_draw = clutter_layer_node_post_draw; | ||||
|   node_class->finalize = clutter_layer_node_finalize; | ||||
|   node_class->serialize = clutter_layer_node_serialize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1539,13 +1412,11 @@ clutter_layer_node_new (const CoglMatrix        *projection, | ||||
| { | ||||
|   ClutterLayerNode *res; | ||||
|   CoglContext *context; | ||||
|   CoglTexture2D *tex_2d; | ||||
|   CoglTexture *texture; | ||||
|   CoglColor color; | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); | ||||
|  | ||||
|   res->update_modelview = TRUE; | ||||
|   res->projection = *projection; | ||||
|   res->viewport = *viewport; | ||||
|   res->fbo_width = width; | ||||
| @@ -1555,10 +1426,9 @@ clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|   /* the texture backing the FBO */ | ||||
|   context = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|   tex_2d = cogl_texture_2d_new_with_size (context, | ||||
|                                           MAX (res->fbo_width, 1), | ||||
|                                           MAX (res->fbo_height, 1)); | ||||
|   texture = COGL_TEXTURE (tex_2d); | ||||
|   texture = cogl_texture_2d_new_with_size (context, | ||||
|                                            MAX (res->fbo_width, 1), | ||||
|                                            MAX (res->fbo_height, 1)); | ||||
|   cogl_texture_set_premultiplied (texture, TRUE); | ||||
|  | ||||
|   res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture)); | ||||
| @@ -1586,245 +1456,3 @@ out: | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_layer_node_new_with_framebuffer: | ||||
|  * @framebuffer: a #CoglFramebuffer | ||||
|  * @pipeline: a #CoglPipeline | ||||
|  * @opacity: the opacity to be used when drawing the layer | ||||
|  * | ||||
|  * Creates a new #ClutterLayerNode with @framebuffer and | ||||
|  * @pipeline. @framebuffer will then be painted using the | ||||
|  * given @opacity. | ||||
|  * | ||||
|  * When using this constructor, the caller is responsible | ||||
|  * for setting up the framebuffer's modelview and projection | ||||
|  * matrices. | ||||
|  * | ||||
|  * Return value: (transfer full)(nullable): the newly created #ClutterLayerNode. | ||||
|  *   Use clutter_paint_node_unref() when done. | ||||
|  */ | ||||
| ClutterPaintNode * | ||||
| clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer, | ||||
|                                          CoglPipeline    *pipeline, | ||||
|                                          guint8           opacity) | ||||
| { | ||||
|   ClutterLayerNode *res; | ||||
|   CoglColor color; | ||||
|  | ||||
|   g_return_val_if_fail (cogl_is_framebuffer (framebuffer), NULL); | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); | ||||
|  | ||||
|   res->update_modelview = FALSE; | ||||
|   res->offscreen = cogl_object_ref (framebuffer); | ||||
|   res->pipeline = cogl_pipeline_copy (pipeline); | ||||
|  | ||||
|   cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|   cogl_pipeline_set_color (res->pipeline, &color); | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * ClutterBlitNode | ||||
|  */ | ||||
|  | ||||
| struct _ClutterBlitNode | ||||
| { | ||||
|   ClutterPaintNode parent_instance; | ||||
|  | ||||
|   CoglFramebuffer *source; | ||||
|   CoglFramebuffer *dest; | ||||
| }; | ||||
|  | ||||
| struct _ClutterBlitNodeClass | ||||
| { | ||||
|   ClutterPaintNodeClass parent_class; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (ClutterBlitNode, clutter_blit_node, CLUTTER_TYPE_PAINT_NODE) | ||||
|  | ||||
| static gboolean | ||||
| clutter_blit_node_pre_draw (ClutterPaintNode    *node, | ||||
|                             ClutterPaintContext *paint_context) | ||||
| { | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_blit_node_draw (ClutterPaintNode    *node, | ||||
|                         ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node); | ||||
|   g_autoptr (GError) error = NULL; | ||||
|   CoglFramebuffer *source; | ||||
|   guint i; | ||||
|  | ||||
|   if (node->operations == NULL) | ||||
|     return; | ||||
|  | ||||
|   source = blit_node->source; | ||||
|   if (!source) | ||||
|     source = clutter_paint_context_get_framebuffer (paint_context); | ||||
|  | ||||
|   for (i = 0; i < node->operations->len; i++) | ||||
|     { | ||||
|       const ClutterPaintOperation *op; | ||||
|       float op_width, op_height; | ||||
|  | ||||
|       op = &g_array_index (node->operations, ClutterPaintOperation, i); | ||||
|  | ||||
|       switch (op->opcode) | ||||
|         { | ||||
|         case PAINT_OP_INVALID: | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_TEX_RECT: | ||||
|           op_width = op->op.texrect[6] - op->op.texrect[4]; | ||||
|           op_height = op->op.texrect[7] - op->op.texrect[5]; | ||||
|  | ||||
|           cogl_blit_framebuffer (source, | ||||
|                                  blit_node->dest, | ||||
|                                  op->op.texrect[0], | ||||
|                                  op->op.texrect[1], | ||||
|                                  op->op.texrect[4], | ||||
|                                  op->op.texrect[5], | ||||
|                                  op_width, | ||||
|                                  op_height, | ||||
|                                  &error); | ||||
|  | ||||
|           if (error) | ||||
|             { | ||||
|               g_warning ("Error blitting framebuffers: %s", error->message); | ||||
|               return; | ||||
|             } | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_blit_node_finalize (ClutterPaintNode *node) | ||||
| { | ||||
|   ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node); | ||||
|  | ||||
|   cogl_clear_object (&blit_node->source); | ||||
|   cogl_clear_object (&blit_node->dest); | ||||
|  | ||||
|   CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node); | ||||
| } | ||||
|  | ||||
| static JsonNode * | ||||
| clutter_blit_node_serialize (ClutterPaintNode *node) | ||||
| { | ||||
|   ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node); | ||||
|   g_autoptr (JsonBuilder) builder = NULL; | ||||
|   g_autofree char *source_ptr = NULL; | ||||
|   g_autofree char *dest_ptr = NULL; | ||||
|  | ||||
|   builder = json_builder_new (); | ||||
|  | ||||
|   source_ptr = g_strdup_printf ("%p", blit_node->source); | ||||
|   dest_ptr = g_strdup_printf ("%p", blit_node->dest); | ||||
|  | ||||
|   json_builder_begin_object (builder); | ||||
|   json_builder_set_member_name (builder, "source"); | ||||
|   json_builder_add_string_value (builder, source_ptr); | ||||
|   json_builder_end_object (builder); | ||||
|  | ||||
|   json_builder_begin_object (builder); | ||||
|   json_builder_set_member_name (builder, "dest"); | ||||
|   json_builder_add_string_value (builder, dest_ptr); | ||||
|   json_builder_end_object (builder); | ||||
|  | ||||
|   return json_builder_get_root (builder); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_blit_node_class_init (ClutterTransformNodeClass *klass) | ||||
| { | ||||
|   ClutterPaintNodeClass *node_class; | ||||
|  | ||||
|   node_class = CLUTTER_PAINT_NODE_CLASS (klass); | ||||
|   node_class->pre_draw = clutter_blit_node_pre_draw; | ||||
|   node_class->draw = clutter_blit_node_draw; | ||||
|   node_class->finalize = clutter_blit_node_finalize; | ||||
|   node_class->serialize = clutter_blit_node_serialize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_blit_node_init (ClutterBlitNode *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_blit_node_new: | ||||
|  * @source: (nullable): the source #CoglFramebuffer | ||||
|  * @dest: the destination #CoglFramebuffer | ||||
|  * | ||||
|  * Creates a new #ClutterBlitNode that blits @source into @dest. | ||||
|  * | ||||
|  * If @source is %NULL, the most recent framebuffer stacked into a | ||||
|  * #ClutterPaintContext is used. | ||||
|  * | ||||
|  * You must only add rectangles using clutter_blit_node_add_blit_rectangle(). | ||||
|  * | ||||
|  * Return value: (transfer full): the newly created #ClutterBlitNode. | ||||
|  *   Use clutter_paint_node_unref() when done. | ||||
|  */ | ||||
| ClutterPaintNode * | ||||
| clutter_blit_node_new (CoglFramebuffer *source, | ||||
|                        CoglFramebuffer *dest) | ||||
| { | ||||
|   ClutterBlitNode *res; | ||||
|  | ||||
|   g_return_val_if_fail (cogl_is_framebuffer (dest), NULL); | ||||
|  | ||||
|   res = _clutter_paint_node_create (CLUTTER_TYPE_BLIT_NODE); | ||||
|   res->source = source ? cogl_object_ref (source) : NULL; | ||||
|   res->dest = cogl_object_ref (dest); | ||||
|  | ||||
|   return (ClutterPaintNode *) res; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_blit_node_add_blit_rectangle: | ||||
|  * @blit_node: a #ClutterBlitNode | ||||
|  * @src_x: Source x position | ||||
|  * @src_y: Source y position | ||||
|  * @dst_x: Destination x position | ||||
|  * @dst_y: Destination y position | ||||
|  * @width: Width of region to copy | ||||
|  * @height: Height of region to copy | ||||
|  * | ||||
|  * Adds a new blit rectangle to the stack of rectangles. All the | ||||
|  * constraints of cogl_blit_framebuffer() apply here. | ||||
|  */ | ||||
| void | ||||
| clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node, | ||||
|                                       int              src_x, | ||||
|                                       int              src_y, | ||||
|                                       int              dst_x, | ||||
|                                       int              dst_y, | ||||
|                                       int              width, | ||||
|                                       int              height) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_BLIT_NODE (blit_node)); | ||||
|  | ||||
|   clutter_paint_node_add_texture_rectangle (CLUTTER_PAINT_NODE (blit_node), | ||||
|                                             &(ClutterActorBox) { | ||||
|                                               src_x, | ||||
|                                               src_y, | ||||
|                                               src_x + width, | ||||
|                                               src_y + height, | ||||
|                                             }, | ||||
|                                             dst_x, | ||||
|                                             dst_y, | ||||
|                                             dst_x + width, | ||||
|                                             dst_y + height); | ||||
| } | ||||
|   | ||||
| @@ -160,8 +160,7 @@ CLUTTER_EXPORT | ||||
| GType clutter_actor_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor, | ||||
|                                            int           opacity); | ||||
| ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor); | ||||
|  | ||||
| #define CLUTTER_TYPE_ROOT_NODE                  (clutter_root_node_get_type ()) | ||||
| #define CLUTTER_ROOT_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode)) | ||||
| @@ -209,11 +208,6 @@ ClutterPaintNode *      clutter_layer_node_new          (const CoglMatrix | ||||
|                                                          float                    height, | ||||
|                                                          guint8                   opacity); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode * clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer, | ||||
|                                                             CoglPipeline    *pipeline, | ||||
|                                                             guint8           opacity); | ||||
|  | ||||
|  | ||||
| #define CLUTTER_TYPE_TRANSFORM_NODE             (clutter_transform_node_get_type ()) | ||||
| #define CLUTTER_TRANSFORM_NODE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode)) | ||||
| @@ -236,38 +230,6 @@ GType clutter_transform_node_get_type (void) G_GNUC_CONST; | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode *      clutter_transform_node_new          (const CoglMatrix *projection); | ||||
|  | ||||
| #define CLUTTER_TYPE_BLIT_NODE                  (clutter_blit_node_get_type ()) | ||||
| #define CLUTTER_BLIT_NODE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLIT_NODE, ClutterBlitNode)) | ||||
| #define CLUTTER_IS_BLIT_NODE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLIT_NODE)) | ||||
|  | ||||
| /* | ||||
|  * ClutterBlitNode: | ||||
|  * | ||||
|  * The #ClutterLayerNode structure is an opaque | ||||
|  * type whose members cannot be directly accessed. | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| typedef struct _ClutterBlitNode                 ClutterBlitNode; | ||||
| typedef struct _ClutterPaintNodeClass           ClutterBlitNodeClass; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_blit_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode * clutter_blit_node_new (CoglFramebuffer *source, | ||||
|                                           CoglFramebuffer *dest); | ||||
|  | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node, | ||||
|                                            int              src_x, | ||||
|                                            int              src_y, | ||||
|                                            int              dst_x, | ||||
|                                            int              dst_y, | ||||
|                                            int              width, | ||||
|                                            int              height); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_PAINT_NODES_H__ */ | ||||
|   | ||||
| @@ -62,7 +62,6 @@ | ||||
| #include "clutter-gesture-action-private.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-timeline.h" | ||||
| #include <math.h> | ||||
|  | ||||
| #define FLOAT_EPSILON   (1e-15) | ||||
| @@ -137,8 +136,7 @@ enum | ||||
|  | ||||
| static guint pan_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, | ||||
|                             CLUTTER_TYPE_GESTURE_ACTION) | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, CLUTTER_TYPE_GESTURE_ACTION) | ||||
|  | ||||
| static void | ||||
| emit_pan (ClutterPanAction *self, | ||||
| @@ -158,18 +156,14 @@ emit_pan (ClutterPanAction *self, | ||||
|           gfloat scroll_threshold = G_PI_4/2; | ||||
|           gfloat drag_angle; | ||||
|  | ||||
|           clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), | ||||
|                                                    0, | ||||
|                                                    &delta_x, | ||||
|                                                    &delta_y); | ||||
|           clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), 0, &delta_x, &delta_y); | ||||
|  | ||||
|           if (delta_x != 0.0f) | ||||
|             drag_angle = atanf (delta_y / delta_x); | ||||
|           else | ||||
|             drag_angle = G_PI_2; | ||||
|  | ||||
|           if ((drag_angle > -scroll_threshold) && | ||||
|               (drag_angle < scroll_threshold)) | ||||
|           if ((drag_angle > -scroll_threshold) && (drag_angle < scroll_threshold)) | ||||
|             priv->pin_state = SCROLL_PINNED_HORIZONTAL; | ||||
|           else if ((drag_angle > (G_PI_2 - scroll_threshold)) || | ||||
|                     (drag_angle < -(G_PI_2 - scroll_threshold))) | ||||
| @@ -288,10 +282,7 @@ gesture_end (ClutterGestureAction *gesture, | ||||
|   gfloat tau; | ||||
|   gint duration; | ||||
|  | ||||
|   clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), | ||||
|                                              0, | ||||
|                                              &priv->release_x, | ||||
|                                              &priv->release_y); | ||||
|   clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), 0, &priv->release_x, &priv->release_y); | ||||
|  | ||||
|   if (!priv->should_interpolate) | ||||
|     { | ||||
| @@ -302,9 +293,7 @@ gesture_end (ClutterGestureAction *gesture, | ||||
|   priv->state = PAN_STATE_INTERPOLATING; | ||||
|  | ||||
|   clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y); | ||||
|   velocity = clutter_gesture_action_get_velocity (gesture, 0, | ||||
|                                                   &velocity_x, | ||||
|                                                   &velocity_y); | ||||
|   velocity = clutter_gesture_action_get_velocity (gesture, 0, &velocity_x, &velocity_y); | ||||
|  | ||||
|   /* Exponential timing constant v(t) = v(0) * exp(-t/tau) | ||||
|    * tau = 1000ms / (frame_per_second * - ln(decay_per_frame)) | ||||
| @@ -315,26 +304,17 @@ gesture_end (ClutterGestureAction *gesture, | ||||
|   /* See where the decreasing velocity reaches $min_velocity px/ms | ||||
|    * v(t) = v(0) * exp(-t/tau) = min_velocity | ||||
|    * t = - tau * ln( min_velocity / |v(0)|) */ | ||||
|   duration = - tau * logf (min_velocity / (ABS (velocity) * | ||||
|                                            priv->acceleration_factor)); | ||||
|   duration = - tau * logf (min_velocity / (ABS (velocity) * priv->acceleration_factor)); | ||||
|  | ||||
|   /* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */ | ||||
|   priv->target_x = (velocity_x * priv->acceleration_factor * tau * | ||||
|                     (1 - exp ((float)-duration / tau))); | ||||
|   priv->target_y = (velocity_y * priv->acceleration_factor * tau * | ||||
|                     (1 - exp ((float)-duration / tau))); | ||||
|   priv->target_x = velocity_x * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau)); | ||||
|   priv->target_y = velocity_y * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau)); | ||||
|  | ||||
|   if (ABS (velocity) * priv->acceleration_factor > min_velocity && | ||||
|       duration > FLOAT_EPSILON) | ||||
|   if (ABS (velocity) * priv->acceleration_factor > min_velocity && duration > FLOAT_EPSILON) | ||||
|     { | ||||
|       ClutterActor *pan_actor = | ||||
|         clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gesture)); | ||||
|  | ||||
|       priv->interpolated_x = priv->interpolated_y = 0.0f; | ||||
|       priv->deceleration_timeline = clutter_timeline_new_for_actor (pan_actor, | ||||
|                                                                     duration); | ||||
|       clutter_timeline_set_progress_mode (priv->deceleration_timeline, | ||||
|                                           CLUTTER_EASE_OUT_EXPO); | ||||
|       priv->deceleration_timeline = clutter_timeline_new (duration); | ||||
|       clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO); | ||||
|  | ||||
|       g_signal_connect (priv->deceleration_timeline, "new_frame", | ||||
|                         G_CALLBACK (on_deceleration_new_frame), self); | ||||
| @@ -387,8 +367,7 @@ clutter_pan_action_set_property (GObject      *gobject, | ||||
|       break; | ||||
|  | ||||
|     case PROP_ACCELERATION_FACTOR : | ||||
|       clutter_pan_action_set_acceleration_factor (self, | ||||
|                                                   g_value_get_double (value)); | ||||
|       clutter_pan_action_set_acceleration_factor (self, g_value_get_double (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
| @@ -432,11 +411,9 @@ static void | ||||
| clutter_pan_action_constructed (GObject *gobject) | ||||
| { | ||||
|   ClutterGestureAction *gesture; | ||||
|   ClutterGestureTriggerEdge edge; | ||||
|  | ||||
|   gesture = CLUTTER_GESTURE_ACTION (gobject); | ||||
|   edge = CLUTTER_GESTURE_TRIGGER_EDGE_AFTER; | ||||
|   clutter_gesture_action_set_threshold_trigger_edge (gesture, edge); | ||||
|   clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_AFTER); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -463,12 +440,9 @@ clutter_pan_action_set_actor (ClutterActorMeta *meta, | ||||
|       /* make sure we reset the state */ | ||||
|       if (priv->state == PAN_STATE_INTERPOLATING) | ||||
|         g_clear_object (&priv->deceleration_timeline); | ||||
|       else if (priv->deceleration_timeline) | ||||
|         clutter_timeline_set_actor (priv->deceleration_timeline, actor); | ||||
|     } | ||||
|  | ||||
|   CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, | ||||
|                                                                          actor); | ||||
|   CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, actor); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -906,9 +880,7 @@ clutter_pan_action_get_constrained_motion_delta (ClutterPanAction *self, | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   distance = clutter_pan_action_get_motion_delta (self, point, | ||||
|                                                   &delta_x, | ||||
|                                                   &delta_y); | ||||
|   distance = clutter_pan_action_get_motion_delta (self, point, &delta_x, &delta_y); | ||||
|  | ||||
|   switch (priv->pan_axis) | ||||
|     { | ||||
|   | ||||
| @@ -37,6 +37,7 @@ | ||||
| #include "clutter-feature.h" | ||||
| #include "clutter-id-pool.h" | ||||
| #include "clutter-layout-manager.h" | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-settings.h" | ||||
| #include "clutter-stage-manager.h" | ||||
| #include "clutter-stage.h" | ||||
| @@ -121,6 +122,9 @@ struct _ClutterMainContext | ||||
|   /* the object holding all the stage instances */ | ||||
|   ClutterStageManager *stage_manager; | ||||
|  | ||||
|   /* the clock driving all the frame operations */ | ||||
|   ClutterMasterClock *master_clock; | ||||
|  | ||||
|   /* the main event queue */ | ||||
|   GQueue *events_queue; | ||||
|  | ||||
| @@ -173,6 +177,11 @@ typedef struct | ||||
| gboolean _clutter_threads_dispatch      (gpointer data); | ||||
| void     _clutter_threads_dispatch_free (gpointer data); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                    _clutter_threads_acquire_lock                   (void); | ||||
| CLUTTER_EXPORT | ||||
| void                    _clutter_threads_release_lock                   (void); | ||||
|  | ||||
| ClutterMainContext *    _clutter_context_get_default                    (void); | ||||
| void                    _clutter_context_lock                           (void); | ||||
| void                    _clutter_context_unlock                         (void); | ||||
| @@ -307,30 +316,6 @@ gboolean        _clutter_run_progress_function  (GType gtype, | ||||
|  | ||||
| void            clutter_timeline_cancel_delay (ClutterTimeline *timeline); | ||||
|  | ||||
| static inline uint64_t | ||||
| us (uint64_t us) | ||||
| { | ||||
|   return us; | ||||
| } | ||||
|  | ||||
| static inline uint64_t | ||||
| ms2us (uint64_t ms) | ||||
| { | ||||
|   return us (ms * 1000); | ||||
| } | ||||
|  | ||||
| static inline uint32_t | ||||
| us2ms (uint64_t us) | ||||
| { | ||||
|   return (uint32_t) (us / 1000); | ||||
| } | ||||
|  | ||||
| static inline uint64_t | ||||
| ns2us (uint64_t ns) | ||||
| { | ||||
|   return us (ns / 1000); | ||||
| } | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -278,26 +278,6 @@ clutter_property_transition_init (ClutterPropertyTransition *self) | ||||
|   self->priv = clutter_property_transition_get_instance_private (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_property_transition_new_for_actor: | ||||
|  * @actor: a #ClutterActor | ||||
|  * @property_name: (allow-none): a property of @animatable, or %NULL | ||||
|  * | ||||
|  * Creates a new #ClutterPropertyTransition. | ||||
|  * | ||||
|  * Return value: (transfer full): the newly created #ClutterPropertyTransition. | ||||
|  *   Use g_object_unref() when done | ||||
|  */ | ||||
| ClutterTransition * | ||||
| clutter_property_transition_new_for_actor (ClutterActor *actor, | ||||
|                                            const char   *property_name) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_PROPERTY_TRANSITION, | ||||
|                        "actor", actor, | ||||
|                        "property-name", property_name, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_property_transition_new: | ||||
|  * @property_name: (allow-none): a property of @animatable, or %NULL | ||||
|   | ||||
| @@ -78,13 +78,8 @@ struct _ClutterPropertyTransitionClass | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_property_transition_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterTransition *     clutter_property_transition_new_for_actor       (ClutterActor              *actor, | ||||
|                                                                          const char                *property_name); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterTransition *     clutter_property_transition_new                 (const char                *property_name); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                    clutter_property_transition_set_property_name   (ClutterPropertyTransition *transition, | ||||
|                                                                          const char                *property_name); | ||||
|   | ||||
| @@ -1523,7 +1523,7 @@ clutter_script_construct_parameters (ClutterScript  *script, | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       if (!(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))) | ||||
|       if (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY)) | ||||
|         { | ||||
|           unparsed = g_list_prepend (unparsed, pinfo); | ||||
|           continue; | ||||
|   | ||||
| @@ -50,14 +50,14 @@ | ||||
|  * <informalexample><programlisting><![CDATA[ | ||||
|  * { | ||||
|  *   "id"     : "red-button", | ||||
|  *   "type"   : "ClutterActor", | ||||
|  *   "type"   : "ClutterRectangle", | ||||
|  *   "width"  : 100, | ||||
|  *   "height" : 100, | ||||
|  *   "background-color" : "#ff0000ff" | ||||
|  *   "color"  : "#ff0000ff" | ||||
|  * } | ||||
|  * ]]></programlisting></informalexample> | ||||
|  * | ||||
|  * This will produce a red #ClutterActor, 100x100 pixels wide, and | ||||
|  * This will produce a red #ClutterRectangle, 100x100 pixels wide, and | ||||
|  * with a ClutterScript id of "red-button"; it can be retrieved by calling: | ||||
|  * | ||||
|  * |[ | ||||
|   | ||||
| @@ -354,17 +354,6 @@ clutter_seat_get_keyboard (ClutterSeat *seat) | ||||
|   return CLUTTER_SEAT_GET_CLASS (seat)->get_keyboard (seat); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_seat_peek_devices: (skip) | ||||
|  **/ | ||||
| const GList * | ||||
| clutter_seat_peek_devices (ClutterSeat *seat) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL); | ||||
|  | ||||
|   return CLUTTER_SEAT_GET_CLASS (seat)->peek_devices (seat); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_seat_list_devices: | ||||
|  * @seat: a #ClutterSeat | ||||
| @@ -381,7 +370,7 @@ clutter_seat_list_devices (ClutterSeat *seat) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL); | ||||
|  | ||||
|   return g_list_copy ((GList *)clutter_seat_peek_devices (seat)); | ||||
|   return CLUTTER_SEAT_GET_CLASS (seat)->list_devices (seat); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -645,8 +634,8 @@ clutter_seat_create_virtual_device (ClutterSeat            *seat, | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_seat_get_supported_virtual_device_types: (skip) | ||||
|  **/ | ||||
|  * clutter_seat_supported_virtual_device_types: (skip) | ||||
|  */ | ||||
| ClutterVirtualDeviceType | ||||
| clutter_seat_get_supported_virtual_device_types (ClutterSeat *seat) | ||||
| { | ||||
| @@ -693,6 +682,7 @@ clutter_seat_warp_pointer (ClutterSeat *seat, | ||||
|  * requirements are fulfilled: | ||||
|  * | ||||
|  *  - A touchscreen is available | ||||
|  *  - No external keyboard is attached to the device | ||||
|  *  - A tablet mode switch, if present, is enabled | ||||
|  * | ||||
|  * Returns: %TRUE if the device is a tablet that doesn't have an external | ||||
|   | ||||
| @@ -96,7 +96,7 @@ struct _ClutterSeatClass | ||||
|   ClutterInputDevice * (* get_pointer)  (ClutterSeat *seat); | ||||
|   ClutterInputDevice * (* get_keyboard) (ClutterSeat *seat); | ||||
|  | ||||
|   const GList * (* peek_devices) (ClutterSeat *seat); | ||||
|   GList * (* list_devices) (ClutterSeat *seat); | ||||
|  | ||||
|   void (* bell_notify) (ClutterSeat *seat); | ||||
|  | ||||
| @@ -133,7 +133,6 @@ CLUTTER_EXPORT | ||||
| ClutterInputDevice * clutter_seat_get_keyboard (ClutterSeat *seat); | ||||
| CLUTTER_EXPORT | ||||
| GList * clutter_seat_list_devices (ClutterSeat *seat); | ||||
| const GList * clutter_seat_peek_devices (ClutterSeat *seat); | ||||
| CLUTTER_EXPORT | ||||
| void clutter_seat_bell_notify (ClutterSeat *seat); | ||||
|  | ||||
|   | ||||
| @@ -384,13 +384,12 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self) | ||||
|  | ||||
| static void | ||||
| clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|                                     ClutterPaintNode       *node, | ||||
|                                     ClutterPaintContext    *paint_context) | ||||
| { | ||||
|   ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect); | ||||
|   ClutterShaderEffectPrivate *priv = self->priv; | ||||
|   ClutterOffscreenEffectClass *parent; | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglHandle material; | ||||
|  | ||||
|   /* If the source hasn't been set then we'll try to get it from the | ||||
|      static source instead */ | ||||
| @@ -408,14 +407,14 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect, | ||||
|  | ||||
|   clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect)); | ||||
|  | ||||
|   /* associate the program to the offscreen target pipeline */ | ||||
|   pipeline = clutter_offscreen_effect_get_pipeline (effect); | ||||
|   cogl_pipeline_set_user_program (pipeline, priv->program); | ||||
|   /* associate the program to the offscreen target material */ | ||||
|   material = clutter_offscreen_effect_get_target (effect); | ||||
|   cogl_pipeline_set_user_program (material, priv->program); | ||||
|  | ||||
| out: | ||||
|   /* paint the offscreen buffer */ | ||||
|   parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class); | ||||
|   parent->paint_target (effect, node, paint_context); | ||||
|   parent->paint_target (effect, paint_context); | ||||
|  | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -40,14 +40,7 @@ void                clutter_stage_paint_view             (ClutterStage | ||||
|                                                           ClutterStageView      *view, | ||||
|                                                           const cairo_region_t  *redraw_clip); | ||||
|  | ||||
| void                clutter_stage_emit_before_update     (ClutterStage          *stage, | ||||
|                                                           ClutterStageView      *view); | ||||
| void                clutter_stage_emit_before_paint      (ClutterStage          *stage, | ||||
|                                                           ClutterStageView      *view); | ||||
| void                clutter_stage_emit_after_paint       (ClutterStage          *stage, | ||||
|                                                           ClutterStageView      *view); | ||||
| void                clutter_stage_emit_after_update      (ClutterStage          *stage, | ||||
|                                                           ClutterStageView      *view); | ||||
| void                _clutter_stage_emit_after_paint      (ClutterStage          *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                _clutter_stage_set_window            (ClutterStage          *stage, | ||||
| @@ -57,6 +50,11 @@ ClutterStageWindow *_clutter_stage_get_window            (ClutterStage | ||||
| void                _clutter_stage_get_projection_matrix (ClutterStage          *stage, | ||||
|                                                           CoglMatrix            *projection); | ||||
| void                _clutter_stage_dirty_projection      (ClutterStage          *stage); | ||||
| void                _clutter_stage_set_viewport          (ClutterStage          *stage, | ||||
|                                                           float                  x, | ||||
|                                                           float                  y, | ||||
|                                                           float                  width, | ||||
|                                                           float                  height); | ||||
| void                _clutter_stage_get_viewport          (ClutterStage          *stage, | ||||
|                                                           float                 *x, | ||||
|                                                           float                 *y, | ||||
| @@ -65,12 +63,9 @@ void                _clutter_stage_get_viewport          (ClutterStage | ||||
| void                _clutter_stage_dirty_viewport        (ClutterStage          *stage); | ||||
| void                _clutter_stage_maybe_setup_viewport  (ClutterStage          *stage, | ||||
|                                                           ClutterStageView      *view); | ||||
| void                clutter_stage_maybe_relayout         (ClutterActor          *stage); | ||||
| void                clutter_stage_maybe_finish_queue_redraws (ClutterStage      *stage); | ||||
| GSList *            clutter_stage_find_updated_devices   (ClutterStage          *stage); | ||||
| void                clutter_stage_update_devices         (ClutterStage          *stage, | ||||
|                                                           GSList                *devices); | ||||
| void                clutter_stage_update_actor_stage_views (ClutterStage        *stage); | ||||
| void                _clutter_stage_maybe_relayout        (ClutterActor          *stage); | ||||
| gboolean            _clutter_stage_needs_update          (ClutterStage          *stage); | ||||
| gboolean            _clutter_stage_do_update             (ClutterStage          *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void     _clutter_stage_queue_event                       (ClutterStage *stage, | ||||
| @@ -79,6 +74,8 @@ void     _clutter_stage_queue_event                       (ClutterStage *stage, | ||||
| gboolean _clutter_stage_has_queued_events                 (ClutterStage *stage); | ||||
| void     _clutter_stage_process_queued_events             (ClutterStage *stage); | ||||
| void     _clutter_stage_update_input_devices              (ClutterStage *stage); | ||||
| gint64    _clutter_stage_get_update_time                  (ClutterStage *stage); | ||||
| void     _clutter_stage_clear_update_time                 (ClutterStage *stage); | ||||
| gboolean _clutter_stage_has_full_redraw_queued            (ClutterStage *stage); | ||||
|  | ||||
| void clutter_stage_log_pick (ClutterStage           *stage, | ||||
| @@ -133,19 +130,17 @@ gboolean                _clutter_stage_update_state     (ClutterStage      *stag | ||||
|  | ||||
| void                    _clutter_stage_set_scale_factor (ClutterStage      *stage, | ||||
|                                                          int                factor); | ||||
| gboolean                _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage    *stage, | ||||
|                                                                            graphene_rect_t *rect, | ||||
|                                                                            float           *view_scale); | ||||
|  | ||||
| void            clutter_stage_presented                 (ClutterStage      *stage, | ||||
|                                                          ClutterStageView  *view, | ||||
| void            _clutter_stage_presented                (ClutterStage      *stage, | ||||
|                                                          CoglFrameEvent     frame_event, | ||||
|                                                          ClutterFrameInfo  *frame_info); | ||||
|  | ||||
| void            clutter_stage_queue_actor_relayout      (ClutterStage *stage, | ||||
|                                                          ClutterActor *actor); | ||||
|  | ||||
| GList * clutter_stage_get_views_for_rect (ClutterStage          *stage, | ||||
|                                           const graphene_rect_t *rect); | ||||
|  | ||||
| void clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -19,7 +19,6 @@ | ||||
| #define __CLUTTER_STAGE_VIEW_PRIVATE_H__ | ||||
|  | ||||
| #include "clutter/clutter-stage-view.h" | ||||
| #include "clutter/clutter-types.h" | ||||
|  | ||||
| void clutter_stage_view_after_paint (ClutterStageView *view, | ||||
|                                      cairo_region_t   *redraw_clip); | ||||
| @@ -63,12 +62,4 @@ void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView | ||||
|                                                     int                          dst_height, | ||||
|                                                     cairo_rectangle_int_t       *dst_rect); | ||||
|  | ||||
| void clutter_stage_view_schedule_update (ClutterStageView *view); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| float clutter_stage_view_get_refresh_rate (ClutterStageView *view); | ||||
|  | ||||
| void clutter_stage_view_notify_presented (ClutterStageView *view, | ||||
|                                           ClutterFrameInfo *frame_info); | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -24,10 +24,8 @@ | ||||
| #include <math.h> | ||||
|  | ||||
| #include "clutter/clutter-damage-history.h" | ||||
| #include "clutter/clutter-frame-clock.h" | ||||
| #include "clutter/clutter-private.h" | ||||
| #include "clutter/clutter-mutter.h" | ||||
| #include "clutter/clutter-stage-private.h" | ||||
| #include "cogl/cogl.h" | ||||
|  | ||||
| enum | ||||
| @@ -35,13 +33,11 @@ enum | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_NAME, | ||||
|   PROP_STAGE, | ||||
|   PROP_LAYOUT, | ||||
|   PROP_FRAMEBUFFER, | ||||
|   PROP_OFFSCREEN, | ||||
|   PROP_USE_SHADOWFB, | ||||
|   PROP_SCALE, | ||||
|   PROP_REFRESH_RATE, | ||||
|  | ||||
|   PROP_LAST | ||||
| }; | ||||
| @@ -52,8 +48,6 @@ typedef struct _ClutterStageViewPrivate | ||||
| { | ||||
|   char *name; | ||||
|  | ||||
|   ClutterStage *stage; | ||||
|  | ||||
|   cairo_rectangle_int_t layout; | ||||
|   float scale; | ||||
|   CoglFramebuffer *framebuffer; | ||||
| @@ -77,9 +71,6 @@ typedef struct _ClutterStageViewPrivate | ||||
|   gboolean has_redraw_clip; | ||||
|   cairo_region_t *redraw_clip; | ||||
|  | ||||
|   float refresh_rate; | ||||
|   ClutterFrameClock *frame_clock; | ||||
|  | ||||
|   guint dirty_viewport   : 1; | ||||
|   guint dirty_projection : 1; | ||||
| } ClutterStageViewPrivate; | ||||
| @@ -111,9 +102,9 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view) | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   if (priv->offscreen) | ||||
|     return COGL_FRAMEBUFFER (priv->offscreen); | ||||
|     return priv->offscreen; | ||||
|   else if (priv->shadow.framebuffer) | ||||
|     return COGL_FRAMEBUFFER (priv->shadow.framebuffer); | ||||
|     return priv->shadow.framebuffer; | ||||
|   else | ||||
|     return priv->framebuffer; | ||||
| } | ||||
| @@ -136,9 +127,8 @@ clutter_stage_view_get_onscreen (ClutterStageView *view) | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen) | ||||
| clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer) | ||||
| { | ||||
|   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen); | ||||
|   CoglPipeline *pipeline; | ||||
|  | ||||
|   pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer)); | ||||
| @@ -147,7 +137,7 @@ clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen) | ||||
|                                    COGL_PIPELINE_FILTER_NEAREST, | ||||
|                                    COGL_PIPELINE_FILTER_NEAREST); | ||||
|   cogl_pipeline_set_layer_texture (pipeline, 0, | ||||
|                                    cogl_offscreen_get_texture (offscreen)); | ||||
|                                    cogl_offscreen_get_texture (framebuffer)); | ||||
|   cogl_pipeline_set_layer_wrap_mode (pipeline, 0, | ||||
|                                      COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); | ||||
|  | ||||
| @@ -168,7 +158,7 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) | ||||
|     return; | ||||
|  | ||||
|   priv->offscreen_pipeline = | ||||
|     clutter_stage_view_create_offscreen_pipeline (priv->offscreen); | ||||
|     clutter_stage_view_create_framebuffer_pipeline (priv->offscreen); | ||||
|  | ||||
|   if (view_class->setup_offscreen_blit_pipeline) | ||||
|     view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline); | ||||
| @@ -202,7 +192,7 @@ clutter_stage_view_transform_rect_to_onscreen (ClutterStageView            *view | ||||
| static void | ||||
| paint_transformed_framebuffer (ClutterStageView     *view, | ||||
|                                CoglPipeline         *pipeline, | ||||
|                                CoglOffscreen        *src_framebuffer, | ||||
|                                CoglFramebuffer      *src_framebuffer, | ||||
|                                CoglFramebuffer      *dst_framebuffer, | ||||
|                                const cairo_region_t *redraw_clip) | ||||
| { | ||||
| @@ -442,13 +432,10 @@ clutter_stage_view_after_paint (ClutterStageView *view, | ||||
|  | ||||
|       if (priv->shadow.framebuffer) | ||||
|         { | ||||
|           CoglFramebuffer *shadowfb = | ||||
|             COGL_FRAMEBUFFER (priv->shadow.framebuffer); | ||||
|  | ||||
|           paint_transformed_framebuffer (view, | ||||
|                                          priv->offscreen_pipeline, | ||||
|                                          priv->offscreen, | ||||
|                                          shadowfb, | ||||
|                                          priv->shadow.framebuffer, | ||||
|                                          redraw_clip); | ||||
|         } | ||||
|       else | ||||
| @@ -521,7 +508,7 @@ find_damaged_tiles (ClutterStageView      *view, | ||||
|   stride = cogl_dma_buf_handle_get_stride (current_dma_buf_handle); | ||||
|   bpp = cogl_dma_buf_handle_get_bpp (current_dma_buf_handle); | ||||
|  | ||||
|   cogl_framebuffer_finish (COGL_FRAMEBUFFER (priv->shadow.framebuffer)); | ||||
|   cogl_framebuffer_finish (priv->shadow.framebuffer); | ||||
|  | ||||
|   if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error)) | ||||
|     return NULL; | ||||
| @@ -614,7 +601,7 @@ swap_dma_buf_framebuffer (ClutterStageView *view) | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|   int next_idx; | ||||
|   CoglDmaBufHandle *next_dma_buf_handle; | ||||
|   CoglFramebuffer *next_framebuffer; | ||||
|   CoglOffscreen *next_framebuffer; | ||||
|  | ||||
|   next_idx = ((priv->shadow.dma_buf.current_idx + 1) % | ||||
|               G_N_ELEMENTS (priv->shadow.dma_buf.handles)); | ||||
| @@ -710,13 +697,12 @@ copy_shadowfb_to_onscreen (ClutterStageView     *view, | ||||
|  | ||||
|   for (i = 0; i < cairo_region_num_rectangles (damage_region); i++) | ||||
|     { | ||||
|       CoglFramebuffer *shadowfb = COGL_FRAMEBUFFER (priv->shadow.framebuffer); | ||||
|       g_autoptr (GError) error = NULL; | ||||
|       cairo_rectangle_int_t rect; | ||||
|  | ||||
|       cairo_region_get_rectangle (damage_region, i, &rect); | ||||
|  | ||||
|       if (!cogl_blit_framebuffer (shadowfb, | ||||
|       if (!cogl_blit_framebuffer (priv->shadow.framebuffer, | ||||
|                                   priv->framebuffer, | ||||
|                                   rect.x, rect.y, | ||||
|                                   rect.x, rect.y, | ||||
| @@ -768,7 +754,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView    *view, | ||||
|  | ||||
|   if (priv->offscreen) | ||||
|     { | ||||
|       callback (COGL_FRAMEBUFFER (priv->offscreen), user_data); | ||||
|       callback (priv->offscreen, user_data); | ||||
|     } | ||||
|   else if (priv->shadow.framebuffer) | ||||
|     { | ||||
| @@ -787,7 +773,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView    *view, | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           callback (COGL_FRAMEBUFFER (priv->shadow.framebuffer), user_data); | ||||
|           callback (priv->shadow.framebuffer, user_data); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
| @@ -1002,154 +988,6 @@ clutter_stage_view_take_scanout (ClutterStageView *view) | ||||
|   return g_steal_pointer (&priv->next_scanout); | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_stage_view_schedule_update (ClutterStageView *view) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   clutter_frame_clock_schedule_update (priv->frame_clock); | ||||
| } | ||||
|  | ||||
| float | ||||
| clutter_stage_view_get_refresh_rate (ClutterStageView *view) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   return priv->refresh_rate; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_view_get_frame_clock: (skip) | ||||
|  */ | ||||
| ClutterFrameClock * | ||||
| clutter_stage_view_get_frame_clock (ClutterStageView *view) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   return priv->frame_clock; | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_frame_clock_before_frame (ClutterFrameClock *frame_clock, | ||||
|                                  int64_t            frame_count, | ||||
|                                  gpointer           user_data) | ||||
| { | ||||
|   ClutterStageView *view = user_data; | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   _clutter_stage_process_queued_events (priv->stage); | ||||
| } | ||||
|  | ||||
| static ClutterFrameResult | ||||
| handle_frame_clock_frame (ClutterFrameClock *frame_clock, | ||||
|                           int64_t            frame_count, | ||||
|                           int64_t            time_us, | ||||
|                           gpointer           user_data) | ||||
| { | ||||
|   ClutterStageView *view = user_data; | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|   ClutterStage *stage = priv->stage; | ||||
|   g_autoptr (GSList) devices = NULL; | ||||
|   ClutterFrameResult result; | ||||
|  | ||||
|   if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) | ||||
|     return CLUTTER_FRAME_RESULT_IDLE; | ||||
|  | ||||
|   if (!clutter_actor_is_realized (CLUTTER_ACTOR (stage))) | ||||
|     return CLUTTER_FRAME_RESULT_IDLE; | ||||
|  | ||||
|   if (!clutter_actor_is_mapped (CLUTTER_ACTOR (stage))) | ||||
|     return CLUTTER_FRAME_RESULT_IDLE; | ||||
|  | ||||
|   _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT); | ||||
|   clutter_stage_emit_before_update (stage, view); | ||||
|  | ||||
|   clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage)); | ||||
|   clutter_stage_update_actor_stage_views (stage); | ||||
|   clutter_stage_maybe_finish_queue_redraws (stage); | ||||
|  | ||||
|   devices = clutter_stage_find_updated_devices (stage); | ||||
|  | ||||
|   if (clutter_stage_view_has_redraw_clip (view)) | ||||
|     { | ||||
|       ClutterStageWindow *stage_window; | ||||
|  | ||||
|       clutter_stage_emit_before_paint (stage, view); | ||||
|  | ||||
|       stage_window = _clutter_stage_get_window (stage); | ||||
|       _clutter_stage_window_redraw_view (stage_window, view); | ||||
|  | ||||
|       clutter_stage_emit_after_paint (stage, view); | ||||
|  | ||||
|       _clutter_stage_window_finish_frame (stage_window); | ||||
|  | ||||
|       result = CLUTTER_FRAME_RESULT_PENDING_PRESENTED; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       result = CLUTTER_FRAME_RESULT_IDLE; | ||||
|     } | ||||
|  | ||||
|   clutter_stage_update_devices (stage, devices); | ||||
|  | ||||
|   _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT); | ||||
|   clutter_stage_emit_after_update (stage, view); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static const ClutterFrameListenerIface frame_clock_listener_iface = { | ||||
|   .before_frame = handle_frame_clock_before_frame, | ||||
|   .frame = handle_frame_clock_frame, | ||||
| }; | ||||
|  | ||||
| void | ||||
| clutter_stage_view_notify_presented (ClutterStageView *view, | ||||
|                                      ClutterFrameInfo *frame_info) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   clutter_stage_presented (priv->stage, view, frame_info); | ||||
|   clutter_frame_clock_notify_presented (priv->frame_clock, frame_info); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sanity_check_framebuffer (ClutterStageView *view) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|   G_GNUC_UNUSED int fb_width, fb_height; | ||||
|  | ||||
|   fb_width = cogl_framebuffer_get_width (priv->framebuffer); | ||||
|   fb_height = cogl_framebuffer_get_height (priv->framebuffer); | ||||
|  | ||||
|   g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) - | ||||
|                          fb_width / priv->scale) < FLT_EPSILON); | ||||
|   g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) - | ||||
|                          fb_height / priv->scale) < FLT_EPSILON); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_view_set_framebuffer (ClutterStageView *view, | ||||
|                                     CoglFramebuffer  *framebuffer) | ||||
| { | ||||
|   ClutterStageViewPrivate *priv = | ||||
|     clutter_stage_view_get_instance_private (view); | ||||
|  | ||||
|   g_warn_if_fail (!priv->framebuffer); | ||||
|   if (framebuffer) | ||||
|     { | ||||
|       priv->framebuffer = cogl_object_ref (framebuffer); | ||||
|       sanity_check_framebuffer (view); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_view_get_property (GObject    *object, | ||||
|                                  guint       prop_id, | ||||
| @@ -1165,9 +1003,6 @@ clutter_stage_view_get_property (GObject    *object, | ||||
|     case PROP_NAME: | ||||
|       g_value_set_string (value, priv->name); | ||||
|       break; | ||||
|     case PROP_STAGE: | ||||
|       g_value_set_boxed (value, &priv->stage); | ||||
|       break; | ||||
|     case PROP_LAYOUT: | ||||
|       g_value_set_boxed (value, &priv->layout); | ||||
|       break; | ||||
| @@ -1183,9 +1018,6 @@ clutter_stage_view_get_property (GObject    *object, | ||||
|     case PROP_SCALE: | ||||
|       g_value_set_float (value, priv->scale); | ||||
|       break; | ||||
|     case PROP_REFRESH_RATE: | ||||
|       g_value_set_float (value, priv->refresh_rate); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|     } | ||||
| @@ -1207,15 +1039,26 @@ clutter_stage_view_set_property (GObject      *object, | ||||
|     case PROP_NAME: | ||||
|       priv->name = g_value_dup_string (value); | ||||
|       break; | ||||
|     case PROP_STAGE: | ||||
|       priv->stage = g_value_get_object (value); | ||||
|       break; | ||||
|     case PROP_LAYOUT: | ||||
|       layout = g_value_get_boxed (value); | ||||
|       priv->layout = *layout; | ||||
|       break; | ||||
|     case PROP_FRAMEBUFFER: | ||||
|       clutter_stage_view_set_framebuffer (view, g_value_get_boxed (value)); | ||||
|       priv->framebuffer = g_value_dup_boxed (value); | ||||
| #ifndef G_DISABLE_CHECKS | ||||
|       if (priv->framebuffer) | ||||
|         { | ||||
|           int fb_width, fb_height; | ||||
|  | ||||
|           fb_width = cogl_framebuffer_get_width (priv->framebuffer); | ||||
|           fb_height = cogl_framebuffer_get_height (priv->framebuffer); | ||||
|  | ||||
|           g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) - | ||||
|                                  fb_width / priv->scale) < FLT_EPSILON); | ||||
|           g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) - | ||||
|                                  fb_height / priv->scale) < FLT_EPSILON); | ||||
|         } | ||||
| #endif | ||||
|       break; | ||||
|     case PROP_OFFSCREEN: | ||||
|       priv->offscreen = g_value_dup_boxed (value); | ||||
| @@ -1226,9 +1069,6 @@ clutter_stage_view_set_property (GObject      *object, | ||||
|     case PROP_SCALE: | ||||
|       priv->scale = g_value_get_float (value); | ||||
|       break; | ||||
|     case PROP_REFRESH_RATE: | ||||
|       priv->refresh_rate = g_value_get_float (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|     } | ||||
| @@ -1244,10 +1084,6 @@ clutter_stage_view_constructed (GObject *object) | ||||
|   if (priv->use_shadowfb) | ||||
|     init_shadowfb (view); | ||||
|  | ||||
|   priv->frame_clock = clutter_frame_clock_new (priv->refresh_rate, | ||||
|                                                &frame_clock_listener_iface, | ||||
|                                                view); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object); | ||||
| } | ||||
|  | ||||
| @@ -1274,7 +1110,6 @@ clutter_stage_view_dispose (GObject *object) | ||||
|   g_clear_pointer (&priv->offscreen, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->redraw_clip, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->frame_clock, clutter_frame_clock_destroy); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); | ||||
| } | ||||
| @@ -1288,7 +1123,6 @@ clutter_stage_view_init (ClutterStageView *view) | ||||
|   priv->dirty_viewport = TRUE; | ||||
|   priv->dirty_projection = TRUE; | ||||
|   priv->scale = 1.0; | ||||
|   priv->refresh_rate = 60.0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1312,16 +1146,6 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) | ||||
|                          G_PARAM_READWRITE | | ||||
|                          G_PARAM_CONSTRUCT_ONLY | | ||||
|                          G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   obj_props[PROP_STAGE] = | ||||
|     g_param_spec_object ("stage", | ||||
|                          "The stage", | ||||
|                          "The ClutterStage", | ||||
|                          CLUTTER_TYPE_STAGE, | ||||
|                          G_PARAM_READWRITE | | ||||
|                          G_PARAM_CONSTRUCT_ONLY | | ||||
|                          G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   obj_props[PROP_LAYOUT] = | ||||
|     g_param_spec_boxed ("layout", | ||||
|                         "View layout", | ||||
| @@ -1367,14 +1191,5 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) | ||||
|                         G_PARAM_CONSTRUCT | | ||||
|                         G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   obj_props[PROP_REFRESH_RATE] = | ||||
|     g_param_spec_float ("refresh-rate", | ||||
|                         "Refresh rate", | ||||
|                         "Update refresh rate", | ||||
|                         1.0, G_MAXFLOAT, 60.0, | ||||
|                         G_PARAM_READWRITE | | ||||
|                         G_PARAM_CONSTRUCT | | ||||
|                         G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   g_object_class_install_properties (object_class, PROP_LAST, obj_props); | ||||
| } | ||||
|   | ||||
| @@ -27,7 +27,6 @@ | ||||
| #include <cogl/cogl.h> | ||||
|  | ||||
| #include "clutter-macros.h" | ||||
| #include "clutter-frame-clock.h" | ||||
|  | ||||
| #define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ()) | ||||
| CLUTTER_EXPORT | ||||
| @@ -70,7 +69,4 @@ CLUTTER_EXPORT | ||||
| void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view, | ||||
|                                                              CoglMatrix       *matrix); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterFrameClock * clutter_stage_view_get_frame_clock (ClutterStageView *view); | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_VIEW_H__ */ | ||||
|   | ||||
| @@ -103,12 +103,81 @@ _clutter_stage_window_get_geometry (ClutterStageWindow    *window, | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_redraw_view (ClutterStageWindow *window, | ||||
|                                    ClutterStageView   *view) | ||||
| _clutter_stage_window_schedule_update  (ClutterStageWindow *window, | ||||
|                                         int                 sync_delay) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); | ||||
|  | ||||
|   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view); | ||||
|   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|   if (iface->schedule_update == NULL) | ||||
|     { | ||||
|       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   iface->schedule_update (window, sync_delay); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * _clutter_stage_window_get_update_time: | ||||
|  * @window: a #ClutterStageWindow object | ||||
|  * | ||||
|  * See _clutter_stage_get_update_time() for more info. | ||||
|  * | ||||
|  * Returns: The timestamp of the update time | ||||
|  */ | ||||
| gint64 | ||||
| _clutter_stage_window_get_update_time (ClutterStageWindow *window) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0); | ||||
|  | ||||
|   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|   if (iface->get_update_time == NULL) | ||||
|     { | ||||
|       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   return iface->get_update_time (window); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * _clutter_stage_window_clear_update_time: | ||||
|  * @window: a #ClutterStageWindow object | ||||
|  * | ||||
|  * Clears the update time. See _clutter_stage_clear_update_time() for more info. | ||||
|  */ | ||||
| void | ||||
| _clutter_stage_window_clear_update_time (ClutterStageWindow *window) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); | ||||
|  | ||||
|   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|   if (iface->clear_update_time == NULL) | ||||
|     { | ||||
|       g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   iface->clear_update_time (window); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_redraw (ClutterStageWindow *window) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); | ||||
|  | ||||
|   iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|   if (iface->redraw) | ||||
|     iface->redraw (window); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
|   | ||||
| @@ -44,8 +44,12 @@ struct _ClutterStageWindowInterface | ||||
|   void              (* get_geometry)            (ClutterStageWindow *stage_window, | ||||
|                                                  cairo_rectangle_int_t *geometry); | ||||
|  | ||||
|   void              (* redraw_view)             (ClutterStageWindow *stage_window, | ||||
|                                                  ClutterStageView   *view); | ||||
|   void              (* schedule_update)         (ClutterStageWindow *stage_window, | ||||
|                                                  int                 sync_delay); | ||||
|   gint64            (* get_update_time)         (ClutterStageWindow *stage_window); | ||||
|   void              (* clear_update_time)       (ClutterStageWindow *stage_window); | ||||
|  | ||||
|   void              (* redraw)                  (ClutterStageWindow *stage_window); | ||||
|  | ||||
|   gboolean          (* can_clip_redraws)        (ClutterStageWindow *stage_window); | ||||
|  | ||||
| @@ -74,12 +78,15 @@ void              _clutter_stage_window_resize                  (ClutterStageWin | ||||
| CLUTTER_EXPORT | ||||
| void              _clutter_stage_window_get_geometry            (ClutterStageWindow *window, | ||||
|                                                                  cairo_rectangle_int_t *geometry); | ||||
| void              _clutter_stage_window_schedule_update         (ClutterStageWindow *window, | ||||
|                                                                  int                 sync_delay); | ||||
| gint64            _clutter_stage_window_get_update_time         (ClutterStageWindow *window); | ||||
| void              _clutter_stage_window_clear_update_time       (ClutterStageWindow *window); | ||||
|  | ||||
| void              _clutter_stage_window_set_accept_focus        (ClutterStageWindow *window, | ||||
|                                                                  gboolean            accept_focus); | ||||
|  | ||||
| void               _clutter_stage_window_redraw_view            (ClutterStageWindow *window, | ||||
|                                                                  ClutterStageView   *view); | ||||
| void              _clutter_stage_window_redraw                  (ClutterStageWindow *window); | ||||
|  | ||||
| gboolean          _clutter_stage_window_can_clip_redraws        (ClutterStageWindow *window); | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -28,8 +28,8 @@ | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <clutter/clutter-actor.h> | ||||
| #include <clutter/clutter-types.h> | ||||
| #include <clutter/clutter-group.h> | ||||
| #include <clutter/clutter-stage-view.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
| @@ -56,7 +56,7 @@ typedef struct _ClutterStagePrivate ClutterStagePrivate; | ||||
| struct _ClutterStage | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|   ClutterGroup parent_instance; | ||||
|  | ||||
|   ClutterStagePrivate *priv; | ||||
| }; | ||||
| @@ -74,7 +74,7 @@ struct _ClutterStage | ||||
| struct _ClutterStageClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|   ClutterGroupClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   /* signals */ | ||||
| @@ -195,10 +195,11 @@ guchar *        clutter_stage_read_pixels                       (ClutterStage | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_ensure_viewport                   (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_ensure_redraw                     (ClutterStage          *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_is_redraw_queued_on_view          (ClutterStage          *stage, | ||||
|                                                                  ClutterStageView      *view); | ||||
| gboolean        clutter_stage_is_redraw_queued                  (ClutterStage          *stage); | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_EXPERIMENTAL_API | ||||
| CLUTTER_EXPORT | ||||
|   | ||||
| @@ -187,6 +187,9 @@ struct _ClutterTextPrivate | ||||
|   ClutterInputContentHintFlags input_hints; | ||||
|   ClutterInputContentPurpose input_purpose; | ||||
|  | ||||
|   /* Signal handler for when the :resource-scale changes */ | ||||
|   gulong resource_scale_changed_id; | ||||
|  | ||||
|   /* bitfields */ | ||||
|   guint alignment               : 2; | ||||
|   guint wrap                    : 1; | ||||
| @@ -595,7 +598,9 @@ ensure_effective_pango_scale_attribute (ClutterText *self) | ||||
|   float resource_scale; | ||||
|   ClutterTextPrivate *priv = self->priv; | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); | ||||
|   if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale) || | ||||
|       resource_scale == 1.0) | ||||
|     return; | ||||
|  | ||||
|   if (priv->effective_attrs != NULL) | ||||
|     { | ||||
| @@ -917,6 +922,18 @@ clutter_text_direction_changed_cb (GObject    *gobject, | ||||
|   /* no need to queue a relayout: set_text_direction() will do that for us */ | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_resource_scale_changed_cb (GObject    *gobject, | ||||
|                                         GParamSpec *pspec) | ||||
| { | ||||
|   ClutterText *self = CLUTTER_TEXT (gobject); | ||||
|   ClutterTextPrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref); | ||||
|   clutter_text_dirty_cache (self); | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject)); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * clutter_text_create_layout: | ||||
|  * @text: a #ClutterText | ||||
| @@ -1120,7 +1137,8 @@ maybe_create_text_layout_with_resource_scale (ClutterText *text, | ||||
| { | ||||
|   float resource_scale; | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text)); | ||||
|   if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale)) | ||||
|     return NULL; | ||||
|  | ||||
|   return create_text_layout_with_scale (text, | ||||
|                                         allocation_width, | ||||
| @@ -1152,7 +1170,8 @@ clutter_text_coords_to_position (ClutterText *self, | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0); | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); | ||||
|   if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale)) | ||||
|     return 0; | ||||
|  | ||||
|   /* Take any offset due to scrolling into account, and normalize | ||||
|    * the coordinates to PangoScale units | ||||
| @@ -1280,7 +1299,8 @@ clutter_text_position_to_coords (ClutterText *self, | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); | ||||
|   if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale)) | ||||
|     return FALSE; | ||||
|  | ||||
|   ret = clutter_text_position_to_coords_internal (self, position, | ||||
|                                                   x, y, line_height); | ||||
| @@ -1756,6 +1776,7 @@ clutter_text_dispose (GObject *gobject) | ||||
|   clutter_text_dirty_cache (self); | ||||
|  | ||||
|   g_clear_signal_handler (&priv->direction_changed_id, self); | ||||
|   g_clear_signal_handler (&priv->resource_scale_changed_id, self); | ||||
|   g_clear_signal_handler (&priv->settings_changed_id, | ||||
|                           clutter_get_default_backend ()); | ||||
|  | ||||
| @@ -2620,7 +2641,8 @@ clutter_text_paint (ClutterActor        *self, | ||||
|       !clutter_text_should_draw_cursor (text)) | ||||
|     return; | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); | ||||
|   if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale)) | ||||
|     return; | ||||
|  | ||||
|   clutter_actor_box_scale (&alloc, resource_scale); | ||||
|   clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height); | ||||
| @@ -2852,7 +2874,8 @@ clutter_text_get_paint_volume (ClutterActor       *self, | ||||
|       if (!clutter_actor_has_allocation (self)) | ||||
|         return FALSE; | ||||
|  | ||||
|       resource_scale = clutter_actor_get_resource_scale (self); | ||||
|       if (!clutter_actor_get_resource_scale (self, &resource_scale)) | ||||
|         return FALSE; | ||||
|  | ||||
|       _clutter_paint_volume_init_static (&priv->paint_volume, self); | ||||
|  | ||||
| @@ -2909,7 +2932,8 @@ clutter_text_get_preferred_width (ClutterActor *self, | ||||
|   gfloat layout_width; | ||||
|   gfloat resource_scale; | ||||
|  | ||||
|   resource_scale = clutter_actor_get_resource_scale (self); | ||||
|   if (!clutter_actor_get_resource_scale (self, &resource_scale)) | ||||
|     resource_scale = 1; | ||||
|  | ||||
|   layout = clutter_text_create_layout (text, -1, -1); | ||||
|   pango_layout_get_extents (layout, NULL, &logical_rect); | ||||
| @@ -2965,7 +2989,8 @@ clutter_text_get_preferred_height (ClutterActor *self, | ||||
|       gfloat layout_height; | ||||
|       gfloat resource_scale; | ||||
|  | ||||
|       resource_scale = clutter_actor_get_resource_scale (self); | ||||
|       if (!clutter_actor_get_resource_scale (self, &resource_scale)) | ||||
|         resource_scale = 1; | ||||
|  | ||||
|       if (priv->single_line_mode) | ||||
|         for_width = -1; | ||||
| @@ -3041,33 +3066,6 @@ clutter_text_has_overlaps (ClutterActor *self) | ||||
|   return clutter_text_should_draw_cursor ((ClutterText *) self); | ||||
| } | ||||
|  | ||||
| static float | ||||
| clutter_text_calculate_resource_scale (ClutterActor *actor, | ||||
|                                        int           phase) | ||||
| { | ||||
|   ClutterActorClass *parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class); | ||||
|   float new_resource_scale; | ||||
|  | ||||
|   new_resource_scale = parent_class->calculate_resource_scale (actor, phase); | ||||
|  | ||||
|   if (phase == 1) | ||||
|     return MAX (new_resource_scale, clutter_actor_get_real_resource_scale (actor)); | ||||
|  | ||||
|   return new_resource_scale; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_resource_scale_changed (ClutterActor *actor) | ||||
| { | ||||
|   ClutterText *text = CLUTTER_TEXT (actor); | ||||
|   ClutterTextPrivate *priv = text->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref); | ||||
|   clutter_text_dirty_cache (text); | ||||
|  | ||||
|   clutter_actor_queue_immediate_relayout (actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_text_im_focus (ClutterText *text) | ||||
| { | ||||
| @@ -3816,8 +3814,6 @@ clutter_text_class_init (ClutterTextClass *klass) | ||||
|   actor_class->key_focus_in = clutter_text_key_focus_in; | ||||
|   actor_class->key_focus_out = clutter_text_key_focus_out; | ||||
|   actor_class->has_overlaps = clutter_text_has_overlaps; | ||||
|   actor_class->calculate_resource_scale = clutter_text_calculate_resource_scale; | ||||
|   actor_class->resource_scale_changed = clutter_text_resource_scale_changed; | ||||
|  | ||||
|   /** | ||||
|    * ClutterText:buffer: | ||||
| @@ -4625,6 +4621,11 @@ clutter_text_init (ClutterText *self) | ||||
|                       NULL); | ||||
|  | ||||
|   priv->input_focus = clutter_text_input_focus_new (self); | ||||
|  | ||||
|   priv->resource_scale_changed_id = | ||||
|     g_signal_connect (self, "notify::resource-scale", | ||||
|                       G_CALLBACK (clutter_text_resource_scale_changed_cb), | ||||
|                       NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By: Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  * | ||||
|  * Copyright (C) 2009  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/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef CLUTTER_TIMELINE_PRIVATE_H | ||||
| #define CLUTTER_TIMELINE_PRIVATE_H | ||||
|  | ||||
| void                    _clutter_timeline_advance                       (ClutterTimeline    *timeline, | ||||
|                                                                          int64_t             tick_time); | ||||
| int64_t                 _clutter_timeline_get_delta                     (ClutterTimeline    *timeline); | ||||
| void                    _clutter_timeline_do_tick                       (ClutterTimeline    *timeline, | ||||
|                                                                          int64_t             tick_time); | ||||
|  | ||||
| #endif /* CLUTTER_TIMELINE_PRIVATE_H */ | ||||
| @@ -95,31 +95,22 @@ | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter-timeline.h" | ||||
| #include "deprecated/clutter-timeline.h" | ||||
|  | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-easing.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-frame-clock.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-scriptable.h" | ||||
| #include "clutter-timeline-private.h" | ||||
|  | ||||
| #include "deprecated/clutter-timeline.h" | ||||
|  | ||||
| struct _ClutterTimelinePrivate | ||||
| { | ||||
|   ClutterTimelineDirection direction; | ||||
|  | ||||
|   ClutterFrameClock *custom_frame_clock; | ||||
|   ClutterFrameClock *frame_clock; | ||||
|  | ||||
|   ClutterActor *actor; | ||||
|   gulong actor_destroy_handler_id; | ||||
|   gulong actor_stage_views_handler_id; | ||||
|   gulong stage_stage_views_handler_id; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   guint delay_id; | ||||
|  | ||||
|   /* The total length in milliseconds of this timeline */ | ||||
| @@ -181,14 +172,13 @@ enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_ACTOR, | ||||
|   PROP_LOOP, | ||||
|   PROP_DELAY, | ||||
|   PROP_DURATION, | ||||
|   PROP_DIRECTION, | ||||
|   PROP_AUTO_REVERSE, | ||||
|   PROP_REPEAT_COUNT, | ||||
|   PROP_PROGRESS_MODE, | ||||
|   PROP_FRAME_CLOCK, | ||||
|  | ||||
|   PROP_LAST | ||||
| }; | ||||
| @@ -209,8 +199,6 @@ enum | ||||
|  | ||||
| static guint timeline_signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| static void update_frame_clock (ClutterTimeline *timeline); | ||||
|  | ||||
| static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT, | ||||
| @@ -302,175 +290,21 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline, | ||||
|   g_hash_table_insert (priv->markers_by_name, marker->name, marker); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_actor_destroyed (ClutterActor    *actor, | ||||
|                     ClutterTimeline *timeline) | ||||
| static inline void | ||||
| clutter_timeline_set_loop_internal (ClutterTimeline *timeline, | ||||
|                                     gboolean         loop) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|   gint old_repeat_count; | ||||
|  | ||||
|   priv->actor = NULL; | ||||
| } | ||||
|   old_repeat_count = timeline->priv->repeat_count; | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_get_actor: | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * | ||||
|  * Get the actor the timeline is associated with. | ||||
|  * | ||||
|  * Returns: (transfer none): the associated #ClutterActor | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_timeline_get_actor (ClutterTimeline *timeline) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|   if (loop) | ||||
|     clutter_timeline_set_repeat_count (timeline, -1); | ||||
|   else | ||||
|     clutter_timeline_set_repeat_count (timeline, 0); | ||||
|  | ||||
|   return priv->actor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_add_timeline (ClutterTimeline *timeline) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|  | ||||
|   if (!priv->frame_clock) | ||||
|     return; | ||||
|  | ||||
|   clutter_frame_clock_add_timeline (priv->frame_clock, timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_remove_timeline (ClutterTimeline *timeline) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|  | ||||
|   if (!priv->frame_clock) | ||||
|     return; | ||||
|  | ||||
|   clutter_frame_clock_remove_timeline (priv->frame_clock, timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_frame_clock_internal (ClutterTimeline   *timeline, | ||||
|                           ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|  | ||||
|   if (priv->frame_clock == frame_clock) | ||||
|     return; | ||||
|  | ||||
|   if (priv->frame_clock && priv->is_playing) | ||||
|     maybe_remove_timeline (timeline); | ||||
|  | ||||
|   g_set_object (&priv->frame_clock, frame_clock); | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (timeline), | ||||
|                             obj_props[PROP_FRAME_CLOCK]); | ||||
|  | ||||
|   if (priv->is_playing) | ||||
|     maybe_add_timeline (timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_stage_stage_views_changed (ClutterActor    *stage, | ||||
|                               ClutterTimeline *timeline) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|  | ||||
|   g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage); | ||||
|   priv->stage = NULL; | ||||
|  | ||||
|   update_frame_clock (timeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_frame_clock (ClutterTimeline *timeline) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|   ClutterFrameClock *frame_clock = NULL; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   if (!priv->actor) | ||||
|     goto out; | ||||
|  | ||||
|   frame_clock = clutter_actor_pick_frame_clock (priv->actor); | ||||
|   if (frame_clock) | ||||
|     { | ||||
|       g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage); | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   stage = clutter_actor_get_stage (priv->actor); | ||||
|   if (!stage) | ||||
|     { | ||||
|       if (priv->is_playing) | ||||
|         g_warning ("Timelines with detached actors are not supported"); | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   if (priv->stage_stage_views_handler_id > 0) | ||||
|     goto out; | ||||
|  | ||||
|   priv->stage_stage_views_handler_id = | ||||
|     g_signal_connect (stage, "stage-views-changed", | ||||
|                       G_CALLBACK (on_stage_stage_views_changed), | ||||
|                       timeline); | ||||
|   priv->stage = stage; | ||||
|  | ||||
| out: | ||||
|   set_frame_clock_internal (timeline, frame_clock); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_actor_stage_views_changed (ClutterActor    *actor, | ||||
|                               ClutterTimeline *timeline) | ||||
| { | ||||
|   update_frame_clock (timeline); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_set_actor: | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * @actor: (nullable): a #ClutterActor | ||||
|  * | ||||
|  * Set the actor the timeline is associated with. | ||||
|  */ | ||||
| void | ||||
| clutter_timeline_set_actor (ClutterTimeline *timeline, | ||||
|                             ClutterActor    *actor) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|  | ||||
|   g_return_if_fail (!actor || (actor && !priv->custom_frame_clock)); | ||||
|  | ||||
|   if (priv->actor) | ||||
|     { | ||||
|       g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor); | ||||
|       g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor); | ||||
|       g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage); | ||||
|       priv->stage = NULL; | ||||
|       priv->actor = NULL; | ||||
|  | ||||
|       if (priv->is_playing) | ||||
|         maybe_remove_timeline (timeline); | ||||
|  | ||||
|       priv->frame_clock = NULL; | ||||
|     } | ||||
|  | ||||
|   priv->actor = actor; | ||||
|  | ||||
|   if (priv->actor) | ||||
|     { | ||||
|       priv->actor_destroy_handler_id = | ||||
|         g_signal_connect (priv->actor, "destroy", | ||||
|                           G_CALLBACK (on_actor_destroyed), | ||||
|                           timeline); | ||||
|       priv->actor_stage_views_handler_id = | ||||
|         g_signal_connect (priv->actor, "stage-views-changed", | ||||
|                           G_CALLBACK (on_actor_stage_views_changed), | ||||
|                           timeline); | ||||
|     } | ||||
|  | ||||
|   update_frame_clock (timeline); | ||||
|   if (old_repeat_count != timeline->priv->repeat_count) | ||||
|     g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_LOOP]); | ||||
| } | ||||
|  | ||||
| /* Scriptable */ | ||||
| @@ -614,8 +448,8 @@ clutter_timeline_set_property (GObject      *object, | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_ACTOR: | ||||
|       clutter_timeline_set_actor (timeline, g_value_get_object (value)); | ||||
|     case PROP_LOOP: | ||||
|       clutter_timeline_set_loop_internal (timeline, g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_DELAY: | ||||
| @@ -642,10 +476,6 @@ clutter_timeline_set_property (GObject      *object, | ||||
|       clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_FRAME_CLOCK: | ||||
|       clutter_timeline_set_frame_clock (timeline, g_value_get_object (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
| @@ -663,8 +493,8 @@ clutter_timeline_get_property (GObject    *object, | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_ACTOR: | ||||
|       g_value_set_object (value, priv->actor); | ||||
|     case PROP_LOOP: | ||||
|       g_value_set_boolean (value, priv->repeat_count != 0); | ||||
|       break; | ||||
|  | ||||
|     case PROP_DELAY: | ||||
| @@ -691,10 +521,6 @@ clutter_timeline_get_property (GObject    *object, | ||||
|       g_value_set_enum (value, priv->progress_mode); | ||||
|       break; | ||||
|  | ||||
|     case PROP_FRAME_CLOCK: | ||||
|       g_value_set_object (value, priv->frame_clock); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
| @@ -706,14 +532,16 @@ clutter_timeline_finalize (GObject *object) | ||||
| { | ||||
|   ClutterTimeline *self = CLUTTER_TIMELINE (object); | ||||
|   ClutterTimelinePrivate *priv = self->priv; | ||||
|   ClutterMasterClock *master_clock; | ||||
|  | ||||
|   if (priv->markers_by_name) | ||||
|     g_hash_table_destroy (priv->markers_by_name); | ||||
|  | ||||
|   if (priv->is_playing) | ||||
|     maybe_remove_timeline (self); | ||||
|  | ||||
|   g_clear_object (&priv->frame_clock); | ||||
|     { | ||||
|       master_clock = _clutter_master_clock_get_default (); | ||||
|       _clutter_master_clock_remove_timeline (master_clock, self); | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object); | ||||
| } | ||||
| @@ -728,14 +556,6 @@ clutter_timeline_dispose (GObject *object) | ||||
|  | ||||
|   clutter_timeline_cancel_delay (self); | ||||
|  | ||||
|   if (priv->actor) | ||||
|     { | ||||
|       g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor); | ||||
|       g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor); | ||||
|       g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage); | ||||
|       priv->actor = NULL; | ||||
|     } | ||||
|  | ||||
|   if (priv->progress_notify != NULL) | ||||
|     { | ||||
|       priv->progress_notify (priv->progress_data); | ||||
| @@ -753,17 +573,24 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   /** | ||||
|    * ClutterTimeline::actor: | ||||
|    * ClutterTimeline:loop: | ||||
|    * | ||||
|    * The actor the timeline is associated with. This will determine what frame | ||||
|    * clock will drive it. | ||||
|    * Whether the timeline should automatically rewind and restart. | ||||
|    * | ||||
|    * As a side effect, setting this property to %TRUE will set the | ||||
|    * #ClutterTimeline:repeat-count property to -1, while setting this | ||||
|    * property to %FALSE will set the #ClutterTimeline:repeat-count | ||||
|    * property to 0. | ||||
|    * | ||||
|    * Deprecated: 1.10: Use the #ClutterTimeline:repeat-count property instead. | ||||
|    */ | ||||
|   obj_props[PROP_ACTOR] = | ||||
|     g_param_spec_object ("actor", | ||||
|                          P_("Actor"), | ||||
|                          P_("Associated ClutterActor"), | ||||
|                          CLUTTER_TYPE_ACTOR, | ||||
|                          G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); | ||||
|   obj_props[PROP_LOOP] = | ||||
|     g_param_spec_boolean ("loop", | ||||
|                           P_("Loop"), | ||||
|                           P_("Should the timeline automatically restart"), | ||||
|                           FALSE, | ||||
|                           CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); | ||||
|  | ||||
|   /** | ||||
|    * ClutterTimeline:delay: | ||||
|    * | ||||
| @@ -862,18 +689,6 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) | ||||
|                        CLUTTER_LINEAR, | ||||
|                        CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterTimeline:frame-clock: | ||||
|    * | ||||
|    * The frame clock driving the timeline. | ||||
|    */ | ||||
|   obj_props[PROP_FRAME_CLOCK] = | ||||
|     g_param_spec_object ("frame-clock", | ||||
|                          "Frame clock", | ||||
|                          "Frame clock driving the timeline", | ||||
|                          CLUTTER_TYPE_FRAME_CLOCK, | ||||
|                          G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   object_class->dispose = clutter_timeline_dispose; | ||||
|   object_class->finalize = clutter_timeline_finalize; | ||||
|   object_class->set_property = clutter_timeline_set_property; | ||||
| @@ -1156,6 +971,7 @@ set_is_playing (ClutterTimeline *timeline, | ||||
|                 gboolean         is_playing) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv = timeline->priv; | ||||
|   ClutterMasterClock *master_clock; | ||||
|  | ||||
|   is_playing = !!is_playing; | ||||
|  | ||||
| @@ -1164,17 +980,15 @@ set_is_playing (ClutterTimeline *timeline, | ||||
|  | ||||
|   priv->is_playing = is_playing; | ||||
|  | ||||
|   master_clock = _clutter_master_clock_get_default (); | ||||
|   if (priv->is_playing) | ||||
|     { | ||||
|       priv->waiting_first_tick = TRUE; | ||||
|       priv->current_repeat = 0; | ||||
|  | ||||
|       maybe_add_timeline (timeline); | ||||
|       _clutter_master_clock_add_timeline (master_clock, timeline); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       maybe_remove_timeline (timeline); | ||||
|     } | ||||
|     _clutter_master_clock_remove_timeline (master_clock, timeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -1371,9 +1185,6 @@ clutter_timeline_start (ClutterTimeline *timeline) | ||||
|   if (priv->duration == 0) | ||||
|     return; | ||||
|  | ||||
|   g_warn_if_fail ((priv->actor && clutter_actor_get_stage (priv->actor)) || | ||||
|                   priv->frame_clock); | ||||
|  | ||||
|   if (priv->delay) | ||||
|     priv->delay_id = clutter_threads_add_timeout (priv->delay, | ||||
|                                                   delay_timeout_func, | ||||
| @@ -1440,6 +1251,45 @@ clutter_timeline_stop (ClutterTimeline *timeline) | ||||
|     g_signal_emit (timeline, timeline_signals[STOPPED], 0, FALSE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_set_loop: | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * @loop: %TRUE for enable looping | ||||
|  * | ||||
|  * Sets whether @timeline should loop. | ||||
|  * | ||||
|  * This function is equivalent to calling clutter_timeline_set_repeat_count() | ||||
|  * with -1 if @loop is %TRUE, and with 0 if @loop is %FALSE. | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_timeline_set_repeat_count() instead. | ||||
|  */ | ||||
| void | ||||
| clutter_timeline_set_loop (ClutterTimeline *timeline, | ||||
| 			   gboolean         loop) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); | ||||
|  | ||||
|   clutter_timeline_set_loop_internal (timeline, loop); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_get_loop: | ||||
|  * @timeline: a #ClutterTimeline | ||||
|  * | ||||
|  * Gets whether @timeline is looping | ||||
|  * | ||||
|  * Return value: %TRUE if the timeline is looping | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_timeline_get_repeat_count() instead. | ||||
|  */ | ||||
| gboolean | ||||
| clutter_timeline_get_loop (ClutterTimeline *timeline) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); | ||||
|  | ||||
|   return timeline->priv->repeat_count != 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_rewind: | ||||
|  * @timeline: A #ClutterTimeline | ||||
| @@ -1556,10 +1406,48 @@ clutter_timeline_is_playing (ClutterTimeline *timeline) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_new: | ||||
|  * @duration_ms: Duration of the timeline in milliseconds | ||||
|  * clutter_timeline_clone: | ||||
|  * @timeline: #ClutterTimeline to duplicate. | ||||
|  * | ||||
|  * Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds. | ||||
|  * Create a new #ClutterTimeline instance which has property values | ||||
|  * matching that of supplied timeline. The cloned timeline will not | ||||
|  * be started and will not be positioned to the current position of | ||||
|  * the original @timeline: you will have to start it with | ||||
|  * clutter_timeline_start(). | ||||
|  * | ||||
|  * The only cloned properties are: | ||||
|  * | ||||
|  *  - #ClutterTimeline:duration | ||||
|  *  - #ClutterTimeline:loop | ||||
|  *  - #ClutterTimeline:delay | ||||
|  *  - #ClutterTimeline:direction | ||||
|  * | ||||
|  * Return value: (transfer full): a new #ClutterTimeline, cloned | ||||
|  *   from @timeline | ||||
|  * | ||||
|  * Since: 0.4 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_timeline_new() or g_object_new() | ||||
|  *   instead | ||||
|  */ | ||||
| ClutterTimeline * | ||||
| clutter_timeline_clone (ClutterTimeline *timeline) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); | ||||
|  | ||||
|   return g_object_new (CLUTTER_TYPE_TIMELINE, | ||||
|                        "duration", timeline->priv->duration, | ||||
|                        "loop", timeline->priv->repeat_count != 0, | ||||
|                        "delay", timeline->priv->delay, | ||||
|                        "direction", timeline->priv->direction, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_new: | ||||
|  * @msecs: Duration of the timeline in milliseconds | ||||
|  * | ||||
|  * Creates a new #ClutterTimeline with a duration of @msecs. | ||||
|  * | ||||
|  * Return value: the newly created #ClutterTimeline instance. Use | ||||
|  *   g_object_unref() when done using it | ||||
| @@ -1567,50 +1455,10 @@ clutter_timeline_is_playing (ClutterTimeline *timeline) | ||||
|  * Since: 0.6 | ||||
|  */ | ||||
| ClutterTimeline * | ||||
| clutter_timeline_new (guint duration_ms) | ||||
| clutter_timeline_new (guint msecs) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_TIMELINE, | ||||
|                        "duration", duration_ms, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_new_for_actor: | ||||
|  * @actor: The #ClutterActor the timeline is associated with | ||||
|  * @duration_ms: Duration of the timeline in milliseconds | ||||
|  * | ||||
|  * Creates a new #ClutterTimeline with a duration of @duration milli seconds. | ||||
|  * | ||||
|  * Return value: the newly created #ClutterTimeline instance. Use | ||||
|  *   g_object_unref() when done using it | ||||
|  */ | ||||
| ClutterTimeline * | ||||
| clutter_timeline_new_for_actor (ClutterActor *actor, | ||||
|                                 unsigned int  duration_ms) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_TIMELINE, | ||||
|                        "duration", duration_ms, | ||||
|                        "actor", actor, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_new_for_frame_clock: | ||||
|  * @frame_clock: The #ClutterFrameClock the timeline is driven by | ||||
|  * @duration_ms: Duration of the timeline in milliseconds | ||||
|  * | ||||
|  * Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds. | ||||
|  * | ||||
|  * Return value: the newly created #ClutterTimeline instance. Use | ||||
|  *   g_object_unref() when done using it | ||||
|  */ | ||||
| ClutterTimeline * | ||||
| clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock, | ||||
|                                       unsigned int       duration_ms) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_TIMELINE, | ||||
|                        "duration", duration_ms, | ||||
|                        "frame-clock", frame_clock, | ||||
|                        "duration", msecs, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| @@ -1876,7 +1724,7 @@ _clutter_timeline_do_tick (ClutterTimeline *timeline, | ||||
|  | ||||
|   /* Check the is_playing variable before performing the timeline tick. | ||||
|    * This is necessary, as if a timeline is stopped in response to a | ||||
|    * frame clock generated signal of a different timeline, this code can | ||||
|    * master-clock generated signal of a different timeline, this code can | ||||
|    * still be reached. | ||||
|    */ | ||||
|   if (!priv->is_playing) | ||||
| @@ -2694,32 +2542,3 @@ clutter_timeline_get_cubic_bezier_progress (ClutterTimeline  *timeline, | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_timeline_get_frame_clock: (skip) | ||||
|  */ | ||||
| ClutterFrameClock * | ||||
| clutter_timeline_get_frame_clock (ClutterTimeline *timeline) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); | ||||
|  | ||||
|   return timeline->priv->frame_clock; | ||||
| } | ||||
|  | ||||
| void | ||||
| clutter_timeline_set_frame_clock (ClutterTimeline   *timeline, | ||||
|                                   ClutterFrameClock *frame_clock) | ||||
| { | ||||
|   ClutterTimelinePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); | ||||
|  | ||||
|   priv = timeline->priv; | ||||
|  | ||||
|   g_assert (!frame_clock || (frame_clock && !priv->actor)); | ||||
|   g_return_if_fail (!frame_clock || (frame_clock && !priv->actor)); | ||||
|  | ||||
|   priv->custom_frame_clock = frame_clock; | ||||
|   if (!priv->actor) | ||||
|     set_frame_clock_internal (timeline, frame_clock); | ||||
| } | ||||
|   | ||||
| @@ -119,19 +119,7 @@ CLUTTER_EXPORT | ||||
| GType clutter_timeline_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterTimeline *               clutter_timeline_new_for_actor                  (ClutterActor             *actor, | ||||
|                                                                                  unsigned int              duration_ms); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterTimeline *               clutter_timeline_new_for_frame_clock            (ClutterFrameClock        *frame_clock, | ||||
|                                                                                  unsigned int              duration_ms); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor *                  clutter_timeline_get_actor                      (ClutterTimeline          *timeline); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                            clutter_timeline_set_actor                      (ClutterTimeline          *timeline, | ||||
|                                                                                  ClutterActor             *actor); | ||||
| ClutterTimeline *               clutter_timeline_new                            (guint                     msecs); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| guint                           clutter_timeline_get_duration                   (ClutterTimeline          *timeline); | ||||
| @@ -233,13 +221,6 @@ gint64                          clutter_timeline_get_duration_hint | ||||
| CLUTTER_EXPORT | ||||
| gint                            clutter_timeline_get_current_repeat             (ClutterTimeline          *timeline); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterFrameClock *             clutter_timeline_get_frame_clock                (ClutterTimeline           *timeline); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                            clutter_timeline_set_frame_clock                (ClutterTimeline           *timeline, | ||||
|                                                                                  ClutterFrameClock         *frame_clock); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* _CLUTTER_TIMELINE_H__ */ | ||||
|   | ||||
| @@ -43,7 +43,6 @@ | ||||
|  | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-timeline-private.h" | ||||
|  | ||||
| struct _ClutterTransitionGroupPrivate | ||||
| { | ||||
|   | ||||
| @@ -364,7 +364,6 @@ clutter_transition_set_animatable (ClutterTransition *transition, | ||||
|                                    ClutterAnimatable *animatable) | ||||
| { | ||||
|   ClutterTransitionPrivate *priv; | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); | ||||
|   g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable)); | ||||
| @@ -384,9 +383,6 @@ clutter_transition_set_animatable (ClutterTransition *transition, | ||||
|       priv->animatable = g_object_ref (animatable); | ||||
|       clutter_transition_attach (transition, priv->animatable); | ||||
|     } | ||||
|  | ||||
|   actor = clutter_animatable_get_actor (animatable); | ||||
|   clutter_timeline_set_actor (CLUTTER_TIMELINE (transition), actor); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -57,7 +57,6 @@ typedef struct _ClutterActorIter                ClutterActorIter; | ||||
| typedef struct _ClutterPaintNode                ClutterPaintNode; | ||||
| typedef struct _ClutterContent                  ClutterContent; /* dummy */ | ||||
| typedef struct _ClutterScrollActor	        ClutterScrollActor; | ||||
| typedef struct _ClutterFrameClock               ClutterFrameClock; | ||||
|  | ||||
| typedef struct _ClutterInterval         	ClutterInterval; | ||||
| typedef struct _ClutterAnimatable       	ClutterAnimatable; /* dummy */ | ||||
| @@ -175,20 +174,6 @@ struct _ClutterActorBox | ||||
|  */ | ||||
| #define CLUTTER_ACTOR_BOX_INIT_ZERO                     CLUTTER_ACTOR_BOX_INIT (0.f, 0.f, 0.f, 0.f) | ||||
|  | ||||
| /** | ||||
|  * CLUTTER_ACTOR_BOX_UNINITIALIZED: | ||||
|  * | ||||
|  * A simple macro for creating a #ClutterActorBox with a size of -1 when | ||||
|  * declaring it, e.g.: | ||||
|  * | ||||
|  * |[ | ||||
|  *   ClutterActorBox box = CLUTTER_ACTOR_BOX_UNINITIALIZED; | ||||
|  * ]| | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #define CLUTTER_ACTOR_BOX_UNINITIALIZED { .x1 = INFINITY, .y1 = INFINITY, .x2 = -INFINITY, .y2 = -INFINITY } | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType            clutter_actor_box_get_type      (void) G_GNUC_CONST; | ||||
| CLUTTER_EXPORT | ||||
| @@ -267,9 +252,6 @@ CLUTTER_EXPORT | ||||
| void             clutter_actor_box_scale          (ClutterActorBox       *box, | ||||
|                                                    gfloat                 scale); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| gboolean         clutter_actor_box_is_initialized (ClutterActorBox       *box); | ||||
|  | ||||
| /** | ||||
|  * ClutterKnot: | ||||
|  * @x: X coordinate of the knot | ||||
|   | ||||
| @@ -63,9 +63,9 @@ | ||||
| #include "clutter-feature.h" | ||||
| #include "clutter-fixed-layout.h" | ||||
| #include "clutter-flow-layout.h" | ||||
| #include "clutter-frame-clock.h" | ||||
| #include "clutter-gesture-action.h" | ||||
| #include "clutter-grid-layout.h" | ||||
| #include "clutter-group.h" | ||||
| #include "clutter-image.h" | ||||
| #include "clutter-input-device.h" | ||||
| #include "clutter-input-device-tool.h" | ||||
|   | ||||
| @@ -47,7 +47,6 @@ | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-stage-private.h" | ||||
| #include "clutter-stage-view-private.h" | ||||
| #include "cogl.h" | ||||
|  | ||||
| #define MAX_STACK_RECTS 256 | ||||
|  | ||||
| @@ -56,25 +55,17 @@ typedef struct _ClutterStageViewCoglPrivate | ||||
|   /* Damage history, in stage view render target framebuffer coordinate space. | ||||
|    */ | ||||
|   ClutterDamageHistory *damage_history; | ||||
|  | ||||
|   guint notify_presented_handle_id; | ||||
| } ClutterStageViewCoglPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl, | ||||
|                             CLUTTER_TYPE_STAGE_VIEW) | ||||
|  | ||||
| typedef struct _ClutterStageCoglPrivate | ||||
| { | ||||
|   int64_t global_frame_counter; | ||||
| } ClutterStageCoglPrivate; | ||||
|  | ||||
| static void | ||||
| clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl, | ||||
|                          _clutter_stage_cogl, | ||||
|                          G_TYPE_OBJECT, | ||||
|                          G_ADD_PRIVATE (ClutterStageCogl) | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, | ||||
|                                                 clutter_stage_window_iface_init)); | ||||
|  | ||||
| @@ -86,12 +77,67 @@ enum | ||||
|   PROP_LAST | ||||
| }; | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window, | ||||
|                                     gint                sync_delay); | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) | ||||
| { | ||||
|   CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_window); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl, | ||||
|                                CoglFrameEvent    frame_event, | ||||
|                                ClutterFrameInfo *frame_info) | ||||
| { | ||||
|  | ||||
|   if (frame_event == COGL_FRAME_EVENT_SYNC) | ||||
|     { | ||||
|       /* Early versions of the swap_event implementation in Mesa | ||||
|        * deliver BufferSwapComplete event when not selected for, | ||||
|        * so if we get a swap event we aren't expecting, just ignore it. | ||||
|        * | ||||
|        * https://bugs.freedesktop.org/show_bug.cgi?id=27962 | ||||
|        * | ||||
|        * FIXME: This issue can be hidden inside Cogl so we shouldn't | ||||
|        * need to care about this bug here. | ||||
|        */ | ||||
|       if (stage_cogl->pending_swaps > 0) | ||||
|         stage_cogl->pending_swaps--; | ||||
|     } | ||||
|   else if (frame_event == COGL_FRAME_EVENT_COMPLETE) | ||||
|     { | ||||
|       gint64 presentation_time_cogl = frame_info->presentation_time; | ||||
|  | ||||
|       if (presentation_time_cogl != 0) | ||||
|         { | ||||
|           ClutterBackend *backend = stage_cogl->backend; | ||||
|           CoglContext *context = clutter_backend_get_cogl_context (backend); | ||||
|           gint64 current_time_cogl = cogl_get_clock_time (context); | ||||
|           gint64 now = g_get_monotonic_time (); | ||||
|  | ||||
|           stage_cogl->last_presentation_time = | ||||
|             now + (presentation_time_cogl - current_time_cogl) / 1000; | ||||
|         } | ||||
|  | ||||
|       stage_cogl->refresh_rate = frame_info->refresh_rate; | ||||
|     } | ||||
|  | ||||
|   _clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info); | ||||
|  | ||||
|   if (frame_event == COGL_FRAME_EVENT_COMPLETE && | ||||
|       stage_cogl->update_time != -1) | ||||
|     { | ||||
|       ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl); | ||||
|  | ||||
|       stage_cogl->update_time = -1; | ||||
|       clutter_stage_cogl_schedule_update (stage_window, | ||||
|                                           stage_cogl->last_sync_delay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_stage_cogl_realize (ClutterStageWindow *stage_window) | ||||
| { | ||||
| @@ -112,14 +158,101 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static int64_t | ||||
| clutter_stage_cogl_get_frame_counter (ClutterStageWindow *stage_window) | ||||
| static void | ||||
| clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window, | ||||
|                                     gint                sync_delay) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|   ClutterStageCoglPrivate *priv = | ||||
|     _clutter_stage_cogl_get_instance_private (stage_cogl); | ||||
|   gint64 now; | ||||
|   float refresh_rate; | ||||
|   gint64 refresh_interval; | ||||
|   int64_t min_render_time_allowed; | ||||
|   int64_t max_render_time_allowed; | ||||
|   int64_t next_presentation_time; | ||||
|  | ||||
|   return priv->global_frame_counter; | ||||
|   if (stage_cogl->update_time != -1) | ||||
|     return; | ||||
|  | ||||
|   stage_cogl->last_sync_delay = sync_delay; | ||||
|  | ||||
|   now = g_get_monotonic_time (); | ||||
|  | ||||
|   if (sync_delay < 0) | ||||
|     { | ||||
|       stage_cogl->update_time = now; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   refresh_rate = stage_cogl->refresh_rate; | ||||
|   if (refresh_rate <= 0.0) | ||||
|     refresh_rate = clutter_get_default_frame_rate (); | ||||
|  | ||||
|   refresh_interval = (gint64) (0.5 + G_USEC_PER_SEC / refresh_rate); | ||||
|   if (refresh_interval == 0) | ||||
|     { | ||||
|       stage_cogl->update_time = now; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   min_render_time_allowed = refresh_interval / 2; | ||||
|   max_render_time_allowed = refresh_interval - 1000 * sync_delay; | ||||
|  | ||||
|   /* Be robust in the case of incredibly bogus refresh rate */ | ||||
|   if (max_render_time_allowed <= 0) | ||||
|     { | ||||
|       g_warning ("Unsupported monitor refresh rate detected. " | ||||
|                  "(Refresh rate: %.3f, refresh interval: %" G_GINT64_FORMAT ")", | ||||
|                  refresh_rate, | ||||
|                  refresh_interval); | ||||
|       stage_cogl->update_time = now; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (min_render_time_allowed > max_render_time_allowed) | ||||
|     min_render_time_allowed = max_render_time_allowed; | ||||
|  | ||||
|   next_presentation_time = stage_cogl->last_presentation_time + refresh_interval; | ||||
|  | ||||
|   /* Get next_presentation_time closer to its final value, to reduce | ||||
|    * the number of while iterations below. | ||||
|    */ | ||||
|   if (next_presentation_time < now) | ||||
|     { | ||||
|       int64_t last_virtual_presentation_time = now - now % refresh_interval; | ||||
|       int64_t hardware_clock_phase = | ||||
|         stage_cogl->last_presentation_time % refresh_interval; | ||||
|  | ||||
|       next_presentation_time = | ||||
|         last_virtual_presentation_time + hardware_clock_phase; | ||||
|     } | ||||
|  | ||||
|   while (next_presentation_time < now + min_render_time_allowed) | ||||
|     next_presentation_time += refresh_interval; | ||||
|  | ||||
|   stage_cogl->update_time = next_presentation_time - max_render_time_allowed; | ||||
|  | ||||
|   if (stage_cogl->update_time == stage_cogl->last_update_time) | ||||
|     stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval; | ||||
| } | ||||
|  | ||||
| static gint64 | ||||
| clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|  | ||||
|   if (stage_cogl->pending_swaps) | ||||
|     return -1; /* in the future, indefinite */ | ||||
|  | ||||
|   return stage_cogl->update_time; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|  | ||||
|   stage_cogl->last_update_time = stage_cogl->update_time; | ||||
|   stage_cogl->update_time = -1; | ||||
| } | ||||
|  | ||||
| static ClutterActor * | ||||
| @@ -222,35 +355,12 @@ paint_damage_region (ClutterStageWindow *stage_window, | ||||
|   cogl_framebuffer_pop_matrix (framebuffer); | ||||
| } | ||||
|  | ||||
| typedef struct _NotifyPresentedClosure | ||||
| { | ||||
|   ClutterStageView *view; | ||||
|   ClutterFrameInfo frame_info; | ||||
| } NotifyPresentedClosure; | ||||
|  | ||||
| static gboolean | ||||
| notify_presented_idle (gpointer user_data) | ||||
| { | ||||
|   NotifyPresentedClosure *closure = user_data; | ||||
|   ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (closure->view); | ||||
|   ClutterStageViewCoglPrivate *view_priv = | ||||
|     clutter_stage_view_cogl_get_instance_private (view_cogl); | ||||
|  | ||||
|   view_priv->notify_presented_handle_id = 0; | ||||
|   clutter_stage_view_notify_presented (closure->view, &closure->frame_info); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| swap_framebuffer (ClutterStageWindow *stage_window, | ||||
|                   ClutterStageView   *view, | ||||
|                   cairo_region_t     *swap_region, | ||||
|                   gboolean            swap_with_damage) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|   ClutterStageCoglPrivate *priv = | ||||
|     _clutter_stage_cogl_get_instance_private (stage_cogl); | ||||
|   CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view); | ||||
|  | ||||
|   clutter_stage_view_before_swap_buffer (view, swap_region); | ||||
| @@ -259,7 +369,6 @@ swap_framebuffer (ClutterStageWindow *stage_window, | ||||
|     { | ||||
|       CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); | ||||
|       int *damage, n_rects, i; | ||||
|       CoglFrameInfo *frame_info; | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (swap_region); | ||||
|       damage = g_newa (int, n_rects * 4); | ||||
| @@ -274,9 +383,6 @@ swap_framebuffer (ClutterStageWindow *stage_window, | ||||
|           damage[i * 4 + 3] = rect.height; | ||||
|         } | ||||
|  | ||||
|       frame_info = cogl_frame_info_new (priv->global_frame_counter); | ||||
|       priv->global_frame_counter++; | ||||
|  | ||||
|       /* push on the screen */ | ||||
|       if (n_rects > 0 && !swap_with_damage) | ||||
|         { | ||||
| @@ -285,8 +391,9 @@ swap_framebuffer (ClutterStageWindow *stage_window, | ||||
|                         onscreen); | ||||
|  | ||||
|           cogl_onscreen_swap_region (onscreen, | ||||
|                                      damage, n_rects, | ||||
|                                      frame_info); | ||||
|                                      damage, n_rects); | ||||
|  | ||||
|           return FALSE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
| @@ -294,35 +401,18 @@ swap_framebuffer (ClutterStageWindow *stage_window, | ||||
|                         onscreen); | ||||
|  | ||||
|           cogl_onscreen_swap_buffers_with_damage (onscreen, | ||||
|                                                   damage, n_rects, | ||||
|                                                   frame_info); | ||||
|                                                   damage, n_rects); | ||||
|  | ||||
|           return TRUE; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view); | ||||
|       ClutterStageViewCoglPrivate *view_priv = | ||||
|         clutter_stage_view_cogl_get_instance_private (view_cogl); | ||||
|       NotifyPresentedClosure *closure; | ||||
|  | ||||
|       CLUTTER_NOTE (BACKEND, "cogl_framebuffer_finish (framebuffer: %p)", | ||||
|                     framebuffer); | ||||
|       cogl_framebuffer_finish (framebuffer); | ||||
|  | ||||
|       closure = g_new0 (NotifyPresentedClosure, 1); | ||||
|       closure->view = view; | ||||
|       closure->frame_info = (ClutterFrameInfo) { | ||||
|         .frame_counter = priv->global_frame_counter, | ||||
|         .refresh_rate = clutter_stage_view_get_refresh_rate (view), | ||||
|         .presentation_time = g_get_monotonic_time (), | ||||
|       }; | ||||
|       priv->global_frame_counter++; | ||||
|  | ||||
|       g_warn_if_fail (view_priv->notify_presented_handle_id == 0); | ||||
|       view_priv->notify_presented_handle_id = | ||||
|         g_idle_add_full (G_PRIORITY_DEFAULT, | ||||
|                          notify_presented_idle, | ||||
|                          closure, g_free); | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -449,11 +539,11 @@ is_buffer_age_enabled (void) | ||||
|          cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, | ||||
|                                         ClutterStageView *view) | ||||
| static gboolean | ||||
| clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, | ||||
|                                 ClutterStageView   *view) | ||||
| { | ||||
|   ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl); | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|   ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view); | ||||
|   ClutterStageViewCoglPrivate *view_priv = | ||||
|     clutter_stage_view_cogl_get_instance_private (view_cogl); | ||||
| @@ -461,7 +551,7 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, | ||||
|   CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view); | ||||
|   cairo_rectangle_int_t view_rect; | ||||
|   gboolean is_full_redraw; | ||||
|   gboolean use_clipped_redraw = TRUE; | ||||
|   gboolean use_clipped_redraw; | ||||
|   gboolean can_blit_sub_buffer; | ||||
|   gboolean has_buffer_age; | ||||
|   gboolean swap_with_damage; | ||||
| @@ -471,7 +561,8 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, | ||||
|   cairo_region_t *swap_region; | ||||
|   float fb_scale; | ||||
|   int fb_width, fb_height; | ||||
|   int buffer_age = 0; | ||||
|   int buffer_age; | ||||
|   gboolean res; | ||||
|  | ||||
|   clutter_stage_view_get_layout (view, &view_rect); | ||||
|   fb_scale = clutter_stage_view_get_scale (view); | ||||
| @@ -538,7 +629,7 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, | ||||
|       redraw_clip = cairo_region_create_rectangle (&view_rect); | ||||
|     } | ||||
|  | ||||
|   g_return_if_fail (!cairo_region_is_empty (fb_clip_region)); | ||||
|   g_return_val_if_fail (!cairo_region_is_empty (fb_clip_region), FALSE); | ||||
|  | ||||
|   swap_with_damage = FALSE; | ||||
|   if (has_buffer_age) | ||||
| @@ -639,12 +730,14 @@ clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl, | ||||
|       cairo_region_destroy (queued_redraw_clip); | ||||
|     } | ||||
|  | ||||
|   swap_framebuffer (stage_window, | ||||
|                     view, | ||||
|                     swap_region, | ||||
|                     swap_with_damage); | ||||
|   res = swap_framebuffer (stage_window, | ||||
|                           view, | ||||
|                           swap_region, | ||||
|                           swap_with_damage); | ||||
|  | ||||
|   cairo_region_destroy (swap_region); | ||||
|  | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -652,34 +745,62 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, | ||||
|                                  ClutterStageView *view, | ||||
|                                  CoglScanout      *scanout) | ||||
| { | ||||
|   ClutterStageCoglPrivate *priv = | ||||
|     _clutter_stage_cogl_get_instance_private (stage_cogl); | ||||
|   CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view); | ||||
|   CoglOnscreen *onscreen; | ||||
|   CoglFrameInfo *frame_info; | ||||
|  | ||||
|   g_return_if_fail (cogl_is_onscreen (framebuffer)); | ||||
|  | ||||
|   onscreen = COGL_ONSCREEN (framebuffer); | ||||
|  | ||||
|   frame_info = cogl_frame_info_new (priv->global_frame_counter); | ||||
|   priv->global_frame_counter++; | ||||
|  | ||||
|   cogl_onscreen_direct_scanout (onscreen, scanout, frame_info); | ||||
|   cogl_onscreen_direct_scanout (onscreen, scanout); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, | ||||
|                                 ClutterStageView   *view) | ||||
| clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|   g_autoptr (CoglScanout) scanout = NULL; | ||||
|   gboolean swap_event = FALSE; | ||||
|   GList *l; | ||||
|  | ||||
|   scanout = clutter_stage_view_take_scanout (view); | ||||
|   if (scanout) | ||||
|     clutter_stage_cogl_scanout_view (stage_cogl, view, scanout); | ||||
|   else | ||||
|     clutter_stage_cogl_redraw_view_primary (stage_cogl, view); | ||||
|   COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)"); | ||||
|  | ||||
|   for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) | ||||
|     { | ||||
|       ClutterStageView *view = l->data; | ||||
|       g_autoptr (CoglScanout) scanout = NULL; | ||||
|  | ||||
|       if (!clutter_stage_view_has_redraw_clip (view)) | ||||
|         continue; | ||||
|  | ||||
|       scanout = clutter_stage_view_take_scanout (view); | ||||
|       if (scanout) | ||||
|         { | ||||
|           clutter_stage_cogl_scanout_view (stage_cogl, | ||||
|                                            view, | ||||
|                                            scanout); | ||||
|           swap_event = TRUE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           swap_event |= clutter_stage_cogl_redraw_view (stage_window, view); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   _clutter_stage_emit_after_paint (stage_cogl->wrapper); | ||||
|  | ||||
|   _clutter_stage_window_finish_frame (stage_window); | ||||
|  | ||||
|   if (swap_event) | ||||
|     { | ||||
|       /* If we have swap buffer events then cogl_onscreen_swap_buffers | ||||
|        * will return immediately and we need to track that there is a | ||||
|        * swap in progress... */ | ||||
|       if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) | ||||
|         stage_cogl->pending_swaps++; | ||||
|     } | ||||
|  | ||||
|   stage_cogl->frame_count++; | ||||
|  | ||||
|   COGL_TRACE_END (ClutterStageCoglRedraw); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -691,8 +812,10 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) | ||||
|   iface->resize = clutter_stage_cogl_resize; | ||||
|   iface->show = clutter_stage_cogl_show; | ||||
|   iface->hide = clutter_stage_cogl_hide; | ||||
|   iface->get_frame_counter = clutter_stage_cogl_get_frame_counter; | ||||
|   iface->redraw_view = clutter_stage_cogl_redraw_view; | ||||
|   iface->schedule_update = clutter_stage_cogl_schedule_update; | ||||
|   iface->get_update_time = clutter_stage_cogl_get_update_time; | ||||
|   iface->clear_update_time = clutter_stage_cogl_clear_update_time; | ||||
|   iface->redraw = clutter_stage_cogl_redraw; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -733,43 +856,10 @@ _clutter_stage_cogl_class_init (ClutterStageCoglClass *klass) | ||||
| static void | ||||
| _clutter_stage_cogl_init (ClutterStageCogl *stage) | ||||
| { | ||||
| } | ||||
|   stage->last_presentation_time = 0; | ||||
|   stage->refresh_rate = 0.0; | ||||
|  | ||||
| static void | ||||
| frame_cb (CoglOnscreen  *onscreen, | ||||
|           CoglFrameEvent frame_event, | ||||
|           CoglFrameInfo *frame_info, | ||||
|           void          *user_data) | ||||
| { | ||||
|   ClutterStageView *view = user_data; | ||||
|   ClutterFrameInfo clutter_frame_info; | ||||
|  | ||||
|   if (frame_event == COGL_FRAME_EVENT_SYNC) | ||||
|     return; | ||||
|  | ||||
|   clutter_frame_info = (ClutterFrameInfo) { | ||||
|     .frame_counter = cogl_frame_info_get_global_frame_counter (frame_info), | ||||
|     .refresh_rate = cogl_frame_info_get_refresh_rate (frame_info), | ||||
|     .presentation_time = ns2us (cogl_frame_info_get_presentation_time (frame_info)), | ||||
|   }; | ||||
|  | ||||
|   clutter_stage_view_notify_presented (view, &clutter_frame_info); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_framebuffer_set (ClutterStageView *view) | ||||
| { | ||||
|   CoglFramebuffer *framebuffer; | ||||
|  | ||||
|   framebuffer = clutter_stage_view_get_onscreen (view); | ||||
|  | ||||
|   if (framebuffer && cogl_is_onscreen (framebuffer)) | ||||
|     { | ||||
|       cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer), | ||||
|                                         frame_cb, | ||||
|                                         view, | ||||
|                                         NULL); | ||||
|     } | ||||
|   stage->update_time = -1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -779,7 +869,6 @@ clutter_stage_view_cogl_finalize (GObject *object) | ||||
|   ClutterStageViewCoglPrivate *view_priv = | ||||
|     clutter_stage_view_cogl_get_instance_private (view_cogl); | ||||
|  | ||||
|   g_clear_handle_id (&view_priv->notify_presented_handle_id, g_source_remove); | ||||
|   clutter_damage_history_free (view_priv->damage_history); | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->finalize (object); | ||||
| @@ -792,9 +881,6 @@ clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl) | ||||
|     clutter_stage_view_cogl_get_instance_private (view_cogl); | ||||
|  | ||||
|   view_priv->damage_history = clutter_damage_history_new (); | ||||
|  | ||||
|   g_signal_connect (view_cogl, "notify::framebuffer", | ||||
|                     G_CALLBACK (on_framebuffer_set), NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -41,6 +41,20 @@ struct _ClutterStageCogl | ||||
|  | ||||
|   /* back pointer to the backend */ | ||||
|   ClutterBackend *backend; | ||||
|  | ||||
|   float refresh_rate; | ||||
|   int pending_swaps; | ||||
|  | ||||
|   gint64 last_presentation_time; | ||||
|   gint64 update_time; | ||||
|   int64_t last_update_time; | ||||
|  | ||||
|   /* 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. */ | ||||
|   unsigned int frame_count; | ||||
|  | ||||
|   gint last_sync_delay; | ||||
| }; | ||||
|  | ||||
| struct _ClutterStageCoglClass | ||||
|   | ||||
							
								
								
									
										114
									
								
								clutter/clutter/deprecated/clutter-actor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								clutter/clutter/deprecated/clutter-actor.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By Matthew Allum  <mallum@openedhand.com> | ||||
|  * | ||||
|  * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd | ||||
|  * Copyright (C) 2009, 2010 Intel Corp | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __CLUTTER_ACTOR_DEPRECATED_H__ | ||||
| #define __CLUTTER_ACTOR_DEPRECATED_H__ | ||||
|  | ||||
| #include <clutter/clutter-types.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| ClutterActor *  clutter_get_actor_by_gid                        (guint32                id_); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_add_child) | ||||
| void            clutter_actor_set_parent                        (ClutterActor          *self, | ||||
|                                                                  ClutterActor          *parent); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_remove_child) | ||||
| void            clutter_actor_unparent                          (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_push_internal                     (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_pop_internal                      (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_show_all                          (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_z_position) | ||||
| void            clutter_actor_set_depth                         (ClutterActor          *self, | ||||
|                                                                  gfloat                 depth); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_z_position) | ||||
| gfloat          clutter_actor_get_depth                         (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle) | ||||
| void            clutter_actor_set_rotation                      (ClutterActor          *self, | ||||
|                                                                  ClutterRotateAxis      axis, | ||||
|                                                                  gdouble                angle, | ||||
|                                                                  gfloat                 x, | ||||
|                                                                  gfloat                 y, | ||||
|                                                                  gfloat                 z); | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle and clutter_actor_set_pivot_point) | ||||
| void            clutter_actor_set_z_rotation_from_gravity       (ClutterActor          *self, | ||||
|                                                                  gdouble                angle, | ||||
|                                                                  ClutterGravity         gravity); | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_rotation_angle) | ||||
| gdouble         clutter_actor_get_rotation                      (ClutterActor          *self, | ||||
|                                                                  ClutterRotateAxis      axis, | ||||
|                                                                  gfloat                *x, | ||||
|                                                                  gfloat                *y, | ||||
|                                                                  gfloat                *z); | ||||
| CLUTTER_DEPRECATED | ||||
| ClutterGravity  clutter_actor_get_z_rotation_gravity            (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_scale and clutter_actor_set_pivot_point) | ||||
| void            clutter_actor_set_scale_full                    (ClutterActor          *self, | ||||
|                                                                  gdouble                scale_x, | ||||
|                                                                  gdouble                scale_y, | ||||
|                                                                  gfloat                 center_x, | ||||
|                                                                  gfloat                 center_y); | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point) | ||||
| void            clutter_actor_get_scale_center                  (ClutterActor          *self, | ||||
|                                                                  gfloat                *center_x, | ||||
|                                                                  gfloat                *center_y); | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point) | ||||
| ClutterGravity  clutter_actor_get_scale_gravity                 (ClutterActor          *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_set_anchor_point                  (ClutterActor          *self, | ||||
|                                                                  gfloat                 anchor_x, | ||||
|                                                                  gfloat                 anchor_y); | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_move_anchor_point                 (ClutterActor          *self, | ||||
|                                                                  gfloat                 anchor_x, | ||||
|                                                                  gfloat                 anchor_y); | ||||
| CLUTTER_DEPRECATED | ||||
| ClutterGravity  clutter_actor_get_anchor_point_gravity          (ClutterActor          *self); | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_set_anchor_point_from_gravity     (ClutterActor          *self, | ||||
|                                                                  ClutterGravity         gravity); | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_actor_move_anchor_point_from_gravity    (ClutterActor          *self, | ||||
|                                                                  ClutterGravity         gravity); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_ACTOR_DEPRECATED_H__ */ | ||||
							
								
								
									
										745
									
								
								clutter/clutter/deprecated/clutter-box.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										745
									
								
								clutter/clutter/deprecated/clutter-box.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,745 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2009,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: | ||||
|  *      Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:clutter-box | ||||
|  * @short_description: A Generic layout container | ||||
|  * | ||||
|  * #ClutterBox is a #ClutterActor sub-class implementing the #ClutterContainer | ||||
|  * interface. A Box delegates the whole size requisition and size allocation to | ||||
|  * a #ClutterLayoutManager instance. | ||||
|  * | ||||
|  * #ClutterBox is available since Clutter 1.2 | ||||
|  * | ||||
|  * #ClutterBox is deprecated since Clutter 1.10; all its relevant API is provided | ||||
|  * by #ClutterActor, via the #ClutterActor:layout-manager property. | ||||
|  * | ||||
|  * ## Using ClutterBox | ||||
|  * | ||||
|  * The following code shows how to create a #ClutterBox with | ||||
|  * a #ClutterLayoutManager sub-class, and how to add children to | ||||
|  * it via clutter_box_pack(). | ||||
|  * | ||||
|  * |[<!-- language="C" --> | ||||
|  *  ClutterActor *box; | ||||
|  *  ClutterLayoutManager *layout; | ||||
|  * | ||||
|  *  // Create the layout manager first | ||||
|  *  layout = clutter_box_layout_new (); | ||||
|  *  clutter_box_layout_set_homogeneous (CLUTTER_BOX_LAYOUT (layout), TRUE); | ||||
|  *  clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12); | ||||
|  * | ||||
|  *  // Then create the ClutterBox actor. The Box will take | ||||
|  *  // ownership of the ClutterLayoutManager instance by sinking | ||||
|  *  // its floating reference | ||||
|  *  box = clutter_box_new (layout); | ||||
|  * | ||||
|  *  // Now add children to the Box using the variadic arguments | ||||
|  *  // function clutter_box_pack() to set layout properties | ||||
|  *  clutter_box_pack (CLUTTER_BOX (box), actor, | ||||
|  *                    "x-align", CLUTTER_BOX_ALIGNMENT_CENTER, | ||||
|  *                    "y-align", CLUTTER_BOX_ALIGNMENT_END, | ||||
|  *                    "expand", TRUE, | ||||
|  *                    NULL); | ||||
|  * ]| | ||||
|  * | ||||
|  * #ClutterBox's clutter_box_pack() wraps the generic | ||||
|  * clutter_container_add_actor() function, but it also allows setting | ||||
|  * layout properties while adding the new child to the box. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <gobject/gvaluecollector.h> | ||||
|  | ||||
| #define CLUTTER_DISABLE_DEPRECATION_WARNINGS | ||||
| #include "deprecated/clutter-container.h" | ||||
|  | ||||
| #include "clutter-box.h" | ||||
|  | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-color.h" | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| struct _ClutterBoxPrivate | ||||
| { | ||||
|   ClutterLayoutManager *manager; | ||||
|  | ||||
|   guint changed_id; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_COLOR, | ||||
|   PROP_COLOR_SET, | ||||
|  | ||||
|   PROP_LAST | ||||
| }; | ||||
|  | ||||
| static GParamSpec *obj_props[PROP_LAST] = { NULL, }; | ||||
|  | ||||
| static const ClutterColor default_box_color = { 255, 255, 255, 255 }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterBox, clutter_box, CLUTTER_TYPE_ACTOR) | ||||
|  | ||||
| static inline void | ||||
| clutter_box_set_color_internal (ClutterBox         *box, | ||||
|                                 const ClutterColor *color) | ||||
| { | ||||
|   clutter_actor_set_background_color (CLUTTER_ACTOR (box), color); | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR_SET]); | ||||
|   g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR]); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_box_real_get_paint_volume (ClutterActor       *actor, | ||||
|                                    ClutterPaintVolume *volume) | ||||
| { | ||||
|   gboolean retval = FALSE; | ||||
|   ClutterActorIter iter; | ||||
|   ClutterActor *child; | ||||
|  | ||||
|   /* if we have a background color, and an allocation, then we need to | ||||
|    * set it as the base of our paint volume | ||||
|    */ | ||||
|   retval = clutter_paint_volume_set_from_allocation (volume, actor); | ||||
|  | ||||
|   /* bail out early if we don't have any child */ | ||||
|   if (clutter_actor_get_n_children (actor) == 0) | ||||
|     return retval; | ||||
|  | ||||
|   retval = TRUE; | ||||
|  | ||||
|   /* otherwise, union the paint volumes of our children, in case | ||||
|    * any one of them decides to paint outside the parent's allocation | ||||
|    */ | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_next (&iter, &child)) | ||||
|     { | ||||
|       const ClutterPaintVolume *child_volume; | ||||
|  | ||||
|       /* This gets the paint volume of the child transformed into the | ||||
|        * group's coordinate space... */ | ||||
|       child_volume = clutter_actor_get_transformed_paint_volume (child, actor); | ||||
|       if (!child_volume) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_paint_volume_union (volume, child_volume); | ||||
|     } | ||||
|  | ||||
|   return retval; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_box_set_property (GObject      *gobject, | ||||
|                           guint         prop_id, | ||||
|                           const GValue *value, | ||||
|                           GParamSpec   *pspec) | ||||
| { | ||||
|   ClutterBox *self = CLUTTER_BOX (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_COLOR: | ||||
|       clutter_box_set_color_internal (self, clutter_value_get_color (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_box_get_property (GObject    *gobject, | ||||
|                           guint       prop_id, | ||||
|                           GValue     *value, | ||||
|                           GParamSpec *pspec) | ||||
| { | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_COLOR: | ||||
|       { | ||||
|         ClutterColor color; | ||||
|  | ||||
|         clutter_actor_get_background_color (CLUTTER_ACTOR (gobject), | ||||
|                                             &color); | ||||
|         clutter_value_set_color (value, &color); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case PROP_COLOR_SET: | ||||
|       { | ||||
|         gboolean color_set; | ||||
|  | ||||
|         g_object_get (gobject, "background-color-set", &color_set, NULL); | ||||
|         g_value_set_boolean (value, color_set); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_box_real_destroy (ClutterActor *actor) | ||||
| { | ||||
|   ClutterActor *iter; | ||||
|  | ||||
|   iter = clutter_actor_get_first_child (actor); | ||||
|   while (iter != NULL) | ||||
|     { | ||||
|       ClutterActor *next = clutter_actor_get_next_sibling (iter); | ||||
|  | ||||
|       clutter_actor_destroy (iter); | ||||
|  | ||||
|       iter = next; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_box_class_init (ClutterBoxClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|  | ||||
|   actor_class->destroy = clutter_box_real_destroy; | ||||
|   actor_class->get_paint_volume = clutter_box_real_get_paint_volume; | ||||
|  | ||||
|   gobject_class->set_property = clutter_box_set_property; | ||||
|   gobject_class->get_property = clutter_box_get_property; | ||||
|  | ||||
|   /** | ||||
|    * ClutterBox:color: | ||||
|    * | ||||
|    * The color to be used to paint the background of the | ||||
|    * #ClutterBox. Setting this property will set the | ||||
|    * #ClutterBox:color-set property as a side effect | ||||
|    * | ||||
|    * This property sets the #ClutterActor:background-color property | ||||
|    * internally. | ||||
|    * | ||||
|    * Since: 1.2 | ||||
|    * | ||||
|    * Deprecated: 1.10: Use the #ClutterActor:background-color property | ||||
|    */ | ||||
|   obj_props[PROP_COLOR] = | ||||
|     clutter_param_spec_color ("color", | ||||
|                               P_("Color"), | ||||
|                               P_("The background color of the box"), | ||||
|                               &default_box_color, | ||||
|                               CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterBox:color-set: | ||||
|    * | ||||
|    * Whether the #ClutterBox:color property has been set. | ||||
|    * | ||||
|    * This property reads the #ClutterActor:background-color-set property | ||||
|    * internally. | ||||
|    * | ||||
|    * Since: 1.2 | ||||
|    * | ||||
|    * Deprecated: 1.10: Use the #ClutterActor:background-color-set property | ||||
|    */ | ||||
|   obj_props[PROP_COLOR_SET] = | ||||
|     g_param_spec_boolean ("color-set", | ||||
|                           P_("Color Set"), | ||||
|                           P_("Whether the background color is set"), | ||||
|                           FALSE, | ||||
|                           CLUTTER_PARAM_READWRITE); | ||||
|  | ||||
|   g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_box_init (ClutterBox *self) | ||||
| { | ||||
|   self->priv = clutter_box_get_instance_private (self); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_new: | ||||
|  * @manager: a #ClutterLayoutManager | ||||
|  * | ||||
|  * Creates a new #ClutterBox. The children of the box will be layed | ||||
|  * out by the passed @manager | ||||
|  * | ||||
|  * Return value: the newly created #ClutterBox actor | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_new() instead. | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_box_new (ClutterLayoutManager *manager) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL); | ||||
|  | ||||
|   return g_object_new (CLUTTER_TYPE_BOX, | ||||
|                        "layout-manager", manager, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_set_layout_manager: | ||||
|  * @box: a #ClutterBox | ||||
|  * @manager: a #ClutterLayoutManager | ||||
|  * | ||||
|  * Sets the #ClutterLayoutManager for @box | ||||
|  * | ||||
|  * A #ClutterLayoutManager is a delegate object that controls the | ||||
|  * layout of the children of @box | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_set_layout_manager() instead. | ||||
|  */ | ||||
| void | ||||
| clutter_box_set_layout_manager (ClutterBox           *box, | ||||
|                                 ClutterLayoutManager *manager) | ||||
| { | ||||
|   clutter_actor_set_layout_manager (CLUTTER_ACTOR (box), manager); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_get_layout_manager: | ||||
|  * @box: a #ClutterBox | ||||
|  * | ||||
|  * Retrieves the #ClutterLayoutManager instance used by @box | ||||
|  * | ||||
|  * Return value: (transfer none): a #ClutterLayoutManager. The returned | ||||
|  *   #ClutterLayoutManager is owned by the #ClutterBox and it should not | ||||
|  *   be unreferenced | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_get_layout_manager() instead. | ||||
|  */ | ||||
| ClutterLayoutManager * | ||||
| clutter_box_get_layout_manager (ClutterBox *box) | ||||
| { | ||||
|   return clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_packv: | ||||
|  * @box: a #ClutterBox | ||||
|  * @actor: a #ClutterActor | ||||
|  * @n_properties: the number of properties to set | ||||
|  * @properties: (array length=n_properties) (element-type utf8): a vector | ||||
|  *   containing the property names to set | ||||
|  * @values: (array length=n_properties): a vector containing the property | ||||
|  *   values to set | ||||
|  * | ||||
|  * Vector-based variant of clutter_box_pack(), intended for language | ||||
|  * bindings to use | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_add_child() instead. To set | ||||
|  *   specific layout properties, use clutter_layout_manager_child_set() | ||||
|  */ | ||||
| void | ||||
| clutter_box_packv (ClutterBox          *box, | ||||
|                    ClutterActor        *actor, | ||||
|                    guint                n_properties, | ||||
|                    const gchar * const  properties[], | ||||
|                    const GValue        *values) | ||||
| { | ||||
|   ClutterLayoutManager *manager; | ||||
|   ClutterContainer *container; | ||||
|   ClutterLayoutMeta *meta; | ||||
|   GObjectClass *klass; | ||||
|   gint i; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (actor)); | ||||
|  | ||||
|   container = CLUTTER_CONTAINER (box); | ||||
|   clutter_container_add_actor (container, actor); | ||||
|  | ||||
|   manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); | ||||
|   if (manager == NULL) | ||||
|     return; | ||||
|  | ||||
|   meta = clutter_layout_manager_get_child_meta (manager, | ||||
|                                                 container, | ||||
|                                                 actor); | ||||
|  | ||||
|   if (meta == NULL) | ||||
|     return; | ||||
|  | ||||
|   klass = G_OBJECT_GET_CLASS (meta); | ||||
|  | ||||
|   for (i = 0; i < n_properties; i++) | ||||
|     { | ||||
|       const gchar *pname = properties[i]; | ||||
|       GParamSpec *pspec; | ||||
|  | ||||
|       pspec = g_object_class_find_property (klass, pname); | ||||
|       if (pspec == NULL) | ||||
|         { | ||||
|           g_warning ("%s: the layout property '%s' for managers " | ||||
|                      "of type '%s' (meta type '%s') does not exist", | ||||
|                      G_STRLOC, | ||||
|                      pname, | ||||
|                      G_OBJECT_TYPE_NAME (manager), | ||||
|                      G_OBJECT_TYPE_NAME (meta)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       if (!(pspec->flags & G_PARAM_WRITABLE)) | ||||
|         { | ||||
|           g_warning ("%s: the layout property '%s' for managers " | ||||
|                      "of type '%s' (meta type '%s') is not writable", | ||||
|                      G_STRLOC, | ||||
|                      pspec->name, | ||||
|                      G_OBJECT_TYPE_NAME (manager), | ||||
|                      G_OBJECT_TYPE_NAME (meta)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       clutter_layout_manager_child_set_property (manager, | ||||
|                                                  container, actor, | ||||
|                                                  pname, &values[i]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| clutter_box_set_property_valist (ClutterBox   *box, | ||||
|                                  ClutterActor *actor, | ||||
|                                  const gchar  *first_property, | ||||
|                                  va_list       var_args) | ||||
| { | ||||
|   ClutterContainer *container = CLUTTER_CONTAINER (box); | ||||
|   ClutterLayoutManager *manager; | ||||
|   ClutterLayoutMeta *meta; | ||||
|   GObjectClass *klass; | ||||
|   const gchar *pname; | ||||
|  | ||||
|   manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box)); | ||||
|   if (manager == NULL) | ||||
|     return; | ||||
|  | ||||
|   meta = clutter_layout_manager_get_child_meta (manager, | ||||
|                                                 container, | ||||
|                                                 actor); | ||||
|  | ||||
|   if (meta == NULL) | ||||
|     return; | ||||
|  | ||||
|   klass = G_OBJECT_GET_CLASS (meta); | ||||
|  | ||||
|   pname = first_property; | ||||
|   while (pname) | ||||
|     { | ||||
|       GValue value = { 0, }; | ||||
|       GParamSpec *pspec; | ||||
|       gchar *error; | ||||
|  | ||||
|       pspec = g_object_class_find_property (klass, pname); | ||||
|       if (pspec == NULL) | ||||
|         { | ||||
|           g_warning ("%s: the layout property '%s' for managers " | ||||
|                      "of type '%s' (meta type '%s') does not exist", | ||||
|                      G_STRLOC, | ||||
|                      pname, | ||||
|                      G_OBJECT_TYPE_NAME (manager), | ||||
|                      G_OBJECT_TYPE_NAME (meta)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       if (!(pspec->flags & G_PARAM_WRITABLE)) | ||||
|         { | ||||
|           g_warning ("%s: the layout property '%s' for managers " | ||||
|                      "of type '%s' (meta type '%s') is not writable", | ||||
|                      G_STRLOC, | ||||
|                      pspec->name, | ||||
|                      G_OBJECT_TYPE_NAME (manager), | ||||
|                      G_OBJECT_TYPE_NAME (meta)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), | ||||
|                             var_args, 0, | ||||
|                             &error); | ||||
|  | ||||
|       if (error) | ||||
|         { | ||||
|           g_warning ("%s: %s", G_STRLOC, error); | ||||
|           g_free (error); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       clutter_layout_manager_child_set_property (manager, | ||||
|                                                  container, actor, | ||||
|                                                  pspec->name, &value); | ||||
|  | ||||
|       g_value_unset (&value); | ||||
|  | ||||
|       pname = va_arg (var_args, gchar*); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_pack: | ||||
|  * @box: a #ClutterBox | ||||
|  * @actor: a #ClutterActor | ||||
|  * @first_property: the name of the first property to set, or %NULL | ||||
|  * @...: a list of property name and value pairs, terminated by %NULL | ||||
|  * | ||||
|  * Adds @actor to @box and sets layout properties at the same time, | ||||
|  * if the #ClutterLayoutManager used by @box has them | ||||
|  * | ||||
|  * This function is a wrapper around clutter_container_add_actor() | ||||
|  * and clutter_layout_manager_child_set() | ||||
|  * | ||||
|  * Language bindings should use the vector-based clutter_box_packv() | ||||
|  * variant instead | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_add_child() instead. To set | ||||
|  *   specific layout properties, use clutter_layout_manager_child_set() | ||||
|  */ | ||||
| void | ||||
| clutter_box_pack (ClutterBox   *box, | ||||
|                   ClutterActor *actor, | ||||
|                   const gchar  *first_property, | ||||
|                   ...) | ||||
| { | ||||
|   va_list var_args; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (actor)); | ||||
|  | ||||
|   clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); | ||||
|  | ||||
|   if (first_property == NULL || *first_property == '\0') | ||||
|     return; | ||||
|  | ||||
|   va_start (var_args, first_property); | ||||
|   clutter_box_set_property_valist (box, actor, first_property, var_args); | ||||
|   va_end (var_args); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_pack_after: | ||||
|  * @box: a #ClutterBox | ||||
|  * @actor: a #ClutterActor | ||||
|  * @sibling: (allow-none): a #ClutterActor or %NULL | ||||
|  * @first_property: the name of the first property to set, or %NULL | ||||
|  * @...: a list of property name and value pairs, terminated by %NULL | ||||
|  * | ||||
|  * Adds @actor to @box, placing it after @sibling, and sets layout | ||||
|  * properties at the same time, if the #ClutterLayoutManager used by | ||||
|  * @box supports them | ||||
|  * | ||||
|  * If @sibling is %NULL then @actor is placed at the end of the | ||||
|  * list of children, to be allocated and painted after every other child | ||||
|  * | ||||
|  * This function is a wrapper around clutter_container_add_actor(), | ||||
|  * clutter_container_raise_child() and clutter_layout_manager_child_set() | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_insert_child_above() instead. | ||||
|  *   To set specific layout properties, use clutter_layout_manager_child_set() | ||||
|  */ | ||||
| void | ||||
| clutter_box_pack_after (ClutterBox   *box, | ||||
|                         ClutterActor *actor, | ||||
|                         ClutterActor *sibling, | ||||
|                         const gchar  *first_property, | ||||
|                         ...) | ||||
| { | ||||
|   va_list var_args; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (actor)); | ||||
|   g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); | ||||
|  | ||||
|   clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); | ||||
|   clutter_container_raise_child (CLUTTER_CONTAINER (box), actor, sibling); | ||||
|  | ||||
|   if (first_property == NULL || *first_property == '\0') | ||||
|     return; | ||||
|  | ||||
|   va_start (var_args, first_property); | ||||
|   clutter_box_set_property_valist (box, actor, first_property, var_args); | ||||
|   va_end (var_args); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_pack_before: | ||||
|  * @box: a #ClutterBox | ||||
|  * @actor: a #ClutterActor | ||||
|  * @sibling: (allow-none): a #ClutterActor or %NULL | ||||
|  * @first_property: the name of the first property to set, or %NULL | ||||
|  * @...: a list of property name and value pairs, terminated by %NULL | ||||
|  * | ||||
|  * Adds @actor to @box, placing it before @sibling, and sets layout | ||||
|  * properties at the same time, if the #ClutterLayoutManager used by | ||||
|  * @box supports them | ||||
|  * | ||||
|  * If @sibling is %NULL then @actor is placed at the beginning of the | ||||
|  * list of children, to be allocated and painted below every other child | ||||
|  * | ||||
|  * This function is a wrapper around clutter_container_add_actor(), | ||||
|  * clutter_container_lower_child() and clutter_layout_manager_child_set() | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_insert_child_below() instead. | ||||
|  *   To set specific layout properties, use clutter_layout_manager_child_set() | ||||
|  */ | ||||
| void | ||||
| clutter_box_pack_before (ClutterBox   *box, | ||||
|                          ClutterActor *actor, | ||||
|                          ClutterActor *sibling, | ||||
|                          const gchar  *first_property, | ||||
|                          ...) | ||||
| { | ||||
|   va_list var_args; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (actor)); | ||||
|   g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling)); | ||||
|  | ||||
|   clutter_container_add_actor (CLUTTER_CONTAINER (box), actor); | ||||
|   clutter_container_lower_child (CLUTTER_CONTAINER (box), actor, sibling); | ||||
|  | ||||
|   if (first_property == NULL || *first_property == '\0') | ||||
|     return; | ||||
|  | ||||
|   va_start (var_args, first_property); | ||||
|   clutter_box_set_property_valist (box, actor, first_property, var_args); | ||||
|   va_end (var_args); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_pack_at: | ||||
|  * @box: a #ClutterBox | ||||
|  * @actor: a #ClutterActor | ||||
|  * @position: the position to insert the @actor at | ||||
|  * @first_property: the name of the first property to set, or %NULL | ||||
|  * @...: a list of property name and value pairs, terminated by %NULL | ||||
|  * | ||||
|  * Adds @actor to @box, placing it at @position, and sets layout | ||||
|  * properties at the same time, if the #ClutterLayoutManager used by | ||||
|  * @box supports them | ||||
|  * | ||||
|  * If @position is a negative number, or is larger than the number of | ||||
|  * children of @box, the new child is added at the end of the list of | ||||
|  * children | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_insert_child_at_index() instead. | ||||
|  *   To set specific layout properties, use clutter_layout_manager_child_set() | ||||
|  */ | ||||
| void | ||||
| clutter_box_pack_at (ClutterBox   *box, | ||||
|                      ClutterActor *actor, | ||||
|                      gint          position, | ||||
|                      const gchar  *first_property, | ||||
|                      ...) | ||||
| { | ||||
|   va_list var_args; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (CLUTTER_IS_ACTOR (actor)); | ||||
|  | ||||
|   clutter_actor_insert_child_at_index (CLUTTER_ACTOR (box), | ||||
|                                        actor, | ||||
|                                        position); | ||||
|  | ||||
|   /* we need to explicitly call this, because we're not going through | ||||
|    * the default code paths provided by clutter_container_add() | ||||
|    */ | ||||
|   clutter_container_create_child_meta (CLUTTER_CONTAINER (box), actor); | ||||
|  | ||||
|   g_signal_emit_by_name (box, "actor-added", actor); | ||||
|  | ||||
|   if (first_property == NULL || *first_property == '\0') | ||||
|     return; | ||||
|  | ||||
|   va_start (var_args, first_property); | ||||
|   clutter_box_set_property_valist (box, actor, first_property, var_args); | ||||
|   va_end (var_args); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_set_color: | ||||
|  * @box: a #ClutterBox | ||||
|  * @color: (allow-none): the background color, or %NULL to unset | ||||
|  * | ||||
|  * Sets (or unsets) the background color for @box | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_set_background_color() instead. | ||||
|  */ | ||||
| void | ||||
| clutter_box_set_color (ClutterBox         *box, | ||||
|                        const ClutterColor *color) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|  | ||||
|   clutter_box_set_color_internal (box, color); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_box_get_color: | ||||
|  * @box: a #ClutterBox | ||||
|  * @color: (out caller-allocates): return location for a #ClutterColor | ||||
|  * | ||||
|  * Retrieves the background color of @box | ||||
|  * | ||||
|  * If the #ClutterBox:color-set property is set to %FALSE the | ||||
|  * returned #ClutterColor is undefined | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_get_background_color() instead. | ||||
|  */ | ||||
| void | ||||
| clutter_box_get_color (ClutterBox   *box, | ||||
|                        ClutterColor *color) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_BOX (box)); | ||||
|   g_return_if_fail (color != NULL); | ||||
|  | ||||
|   clutter_actor_get_background_color (CLUTTER_ACTOR (box), color); | ||||
| } | ||||
							
								
								
									
										143
									
								
								clutter/clutter/deprecated/clutter-box.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								clutter/clutter/deprecated/clutter-box.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2009,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: | ||||
|  *      Emmanuele Bassi <ebassi@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __CLUTTER_BOX_H__ | ||||
| #define __CLUTTER_BOX_H__ | ||||
|  | ||||
| #include <clutter/clutter-actor.h> | ||||
| #include <clutter/clutter-container.h> | ||||
| #include <clutter/clutter-layout-manager.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_BOX                (clutter_box_get_type ()) | ||||
| #define CLUTTER_BOX(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX, ClutterBox)) | ||||
| #define CLUTTER_IS_BOX(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX)) | ||||
| #define CLUTTER_BOX_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX, ClutterBoxClass)) | ||||
| #define CLUTTER_IS_BOX_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX)) | ||||
| #define CLUTTER_BOX_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX, ClutterBoxClass)) | ||||
|  | ||||
| typedef struct _ClutterBox              ClutterBox; | ||||
| typedef struct _ClutterBoxPrivate       ClutterBoxPrivate; | ||||
| typedef struct _ClutterBoxClass         ClutterBoxClass; | ||||
|  | ||||
| /** | ||||
|  * ClutterBox: | ||||
|  * | ||||
|  * The #ClutterBox structure contains only private data and should | ||||
|  * be accessed using the provided API | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| struct _ClutterBox | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent_instance; | ||||
|  | ||||
|   ClutterBoxPrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * ClutterBoxClass: | ||||
|  * | ||||
|  * The #ClutterBoxClass structure contains only private data | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| struct _ClutterBoxClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding, for future expansion */ | ||||
|   void (*clutter_padding_1) (void); | ||||
|   void (*clutter_padding_2) (void); | ||||
|   void (*clutter_padding_3) (void); | ||||
|   void (*clutter_padding_4) (void); | ||||
|   void (*clutter_padding_5) (void); | ||||
|   void (*clutter_padding_6) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| GType clutter_box_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_new) | ||||
| ClutterActor *        clutter_box_new                (ClutterLayoutManager *manager); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_layout_manager) | ||||
| void                  clutter_box_set_layout_manager (ClutterBox           *box, | ||||
|                                                       ClutterLayoutManager *manager); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_layout_manager) | ||||
| ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox           *box); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color) | ||||
| void                  clutter_box_set_color          (ClutterBox           *box, | ||||
|                                                       const ClutterColor   *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color) | ||||
| void                  clutter_box_get_color          (ClutterBox           *box, | ||||
|                                                       ClutterColor         *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_add_child) | ||||
| void                  clutter_box_pack               (ClutterBox           *box, | ||||
|                                                       ClutterActor         *actor, | ||||
|                                                       const gchar          *first_property, | ||||
|                                                       ...); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_add_child) | ||||
| void                  clutter_box_packv              (ClutterBox           *box, | ||||
|                                                       ClutterActor         *actor, | ||||
|                                                       guint                 n_properties, | ||||
|                                                       const gchar * const   properties[], | ||||
|                                                       const GValue         *values); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_above) | ||||
| void                  clutter_box_pack_after         (ClutterBox           *box, | ||||
|                                                       ClutterActor         *actor, | ||||
|                                                       ClutterActor         *sibling, | ||||
|                                                       const gchar          *first_property, | ||||
|                                                       ...); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_below) | ||||
| void                  clutter_box_pack_before        (ClutterBox           *box, | ||||
|                                                       ClutterActor         *actor, | ||||
|                                                       ClutterActor         *sibling, | ||||
|                                                       const gchar          *first_property, | ||||
|                                                       ...); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_at_index) | ||||
| void                  clutter_box_pack_at            (ClutterBox           *box, | ||||
|                                                       ClutterActor         *actor, | ||||
|                                                       gint                  position, | ||||
|                                                       const gchar          *first_property, | ||||
|                                                       ...); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_BOX_H__ */ | ||||
							
								
								
									
										554
									
								
								clutter/clutter/deprecated/clutter-group.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										554
									
								
								clutter/clutter/deprecated/clutter-group.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,554 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By Matthew Allum  <mallum@openedhand.com> | ||||
|  * | ||||
|  * 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, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:clutter-group | ||||
|  * @short_description: A fixed layout container | ||||
|  * | ||||
|  * A #ClutterGroup is an Actor which contains multiple child actors positioned | ||||
|  * relative to the #ClutterGroup position. Other operations such as scaling, | ||||
|  * rotating and clipping of the group will apply to the child actors. | ||||
|  * | ||||
|  * A #ClutterGroup's size is defined by the size and position of its children; | ||||
|  * it will be the smallest non-negative size that covers the right and bottom | ||||
|  * edges of all of its children. | ||||
|  * | ||||
|  * Setting the size on a Group using #ClutterActor methods like | ||||
|  * clutter_actor_set_size() will override the natural size of the Group, | ||||
|  * however this will not affect the size of the children and they may still | ||||
|  * be painted outside of the allocation of the group. One way to constrain | ||||
|  * the visible area of a #ClutterGroup to a specified allocation is to | ||||
|  * explicitly set the size of the #ClutterGroup and then use the | ||||
|  * #ClutterActor:clip-to-allocation property. | ||||
|  * | ||||
|  * #ClutterGroup as a concrete class has been superceded by #ClutterActor | ||||
|  * since Clutter 1.10. The type itself is not deprecated as it is used by | ||||
|  * #ClutterStage. You should instantiate #ClutterActor and use its API to | ||||
|  * manage child actors. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include <stdarg.h> | ||||
|  | ||||
| #define CLUTTER_DISABLE_DEPRECATION_WARNINGS | ||||
| #include "clutter-group.h" | ||||
|  | ||||
| #include "clutter-actor.h" | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-container.h" | ||||
| #include "clutter-fixed-layout.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| #include "cogl/cogl.h" | ||||
|  | ||||
| struct _ClutterGroupPrivate | ||||
| { | ||||
|   GList *children; | ||||
|  | ||||
|   ClutterLayoutManager *layout; | ||||
| }; | ||||
|  | ||||
| static void clutter_container_iface_init (ClutterContainerIface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (ClutterGroup, clutter_group, CLUTTER_TYPE_ACTOR, | ||||
|                          G_ADD_PRIVATE (ClutterGroup) | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, | ||||
|                                                 clutter_container_iface_init)); | ||||
|  | ||||
| static gint | ||||
| sort_by_depth (gconstpointer a, | ||||
|                gconstpointer b) | ||||
| { | ||||
|   gfloat depth_a = clutter_actor_get_depth (CLUTTER_ACTOR(a)); | ||||
|   gfloat depth_b = clutter_actor_get_depth (CLUTTER_ACTOR(b)); | ||||
|  | ||||
|   if (depth_a < depth_b) | ||||
|     return -1; | ||||
|  | ||||
|   if (depth_a > depth_b) | ||||
|     return 1; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_add (ClutterContainer *container, | ||||
|                         ClutterActor     *actor) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   g_object_ref (actor); | ||||
|  | ||||
|   priv->children = g_list_append (priv->children, actor); | ||||
|   clutter_actor_set_parent (actor, CLUTTER_ACTOR (container)); | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); | ||||
|  | ||||
|   g_signal_emit_by_name (container, "actor-added", actor); | ||||
|  | ||||
|   clutter_container_sort_depth_order (container); | ||||
|  | ||||
|   g_object_unref (actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_actor_added (ClutterContainer *container, | ||||
|                                 ClutterActor     *actor) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   /* XXX - children added using clutter_actor_add_child() will | ||||
|    * cause actor-added to be emitted without going through the | ||||
|    * add() virtual function. | ||||
|    * | ||||
|    * if we get an actor-added for a child that is not in our | ||||
|    * list of children already, then we go in compatibility | ||||
|    * mode. | ||||
|    */ | ||||
|   if (g_list_find (priv->children, actor) != NULL) | ||||
|     return; | ||||
|  | ||||
|   priv->children = g_list_append (priv->children, actor); | ||||
|   clutter_container_sort_depth_order (container); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_remove (ClutterContainer *container, | ||||
|                            ClutterActor     *actor) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   g_object_ref (actor); | ||||
|  | ||||
|   priv->children = g_list_remove (priv->children, actor); | ||||
|   clutter_actor_unparent (actor); | ||||
|  | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (container)); | ||||
|  | ||||
|   g_signal_emit_by_name (container, "actor-removed", actor); | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); | ||||
|  | ||||
|   g_object_unref (actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_actor_removed (ClutterContainer *container, | ||||
|                                   ClutterActor     *actor) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   /* XXX - same compatibility mode of the ::actor-added implementation */ | ||||
|   if (g_list_find (priv->children, actor) == NULL) | ||||
|     return; | ||||
|  | ||||
|   priv->children = g_list_remove (priv->children, actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_raise (ClutterContainer *container, | ||||
|                           ClutterActor     *actor, | ||||
|                           ClutterActor     *sibling) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   priv->children = g_list_remove (priv->children, actor); | ||||
|  | ||||
|   /* Raise at the top */ | ||||
|   if (!sibling) | ||||
|     { | ||||
|       GList *last_item; | ||||
|  | ||||
|       last_item = g_list_last (priv->children); | ||||
|  | ||||
|       if (last_item) | ||||
| 	sibling = last_item->data; | ||||
|  | ||||
|       priv->children = g_list_append (priv->children, actor); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       gint index_ = g_list_index (priv->children, sibling) + 1; | ||||
|  | ||||
|       priv->children = g_list_insert (priv->children, actor, index_); | ||||
|     } | ||||
|  | ||||
|   /* set Z ordering a value below, this will then call sort | ||||
|    * as values are equal ordering shouldn't change but Z | ||||
|    * values will be correct. | ||||
|    * | ||||
|    * FIXME: get rid of this crap; this is so utterly broken and wrong on | ||||
|    * so many levels it's not even funny. sadly, we get to keep this until | ||||
|    * we can break API and remove Group for good. | ||||
|    */ | ||||
|   if (sibling && | ||||
|       clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) | ||||
|     { | ||||
|       clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_lower (ClutterContainer *container, | ||||
|                           ClutterActor     *actor, | ||||
|                           ClutterActor     *sibling) | ||||
| { | ||||
|   ClutterGroup *self = CLUTTER_GROUP (container); | ||||
|   ClutterGroupPrivate *priv = self->priv; | ||||
|  | ||||
|   priv->children = g_list_remove (priv->children, actor); | ||||
|  | ||||
|   /* Push to bottom */ | ||||
|   if (!sibling) | ||||
|     { | ||||
|       GList *last_item; | ||||
|  | ||||
|       last_item = g_list_first (priv->children); | ||||
|  | ||||
|       if (last_item) | ||||
| 	sibling = last_item->data; | ||||
|  | ||||
|       priv->children = g_list_prepend (priv->children, actor); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       gint index_ = g_list_index (priv->children, sibling); | ||||
|  | ||||
|       priv->children = g_list_insert (priv->children, actor, index_); | ||||
|     } | ||||
|  | ||||
|   /* See comment in group_raise for this */ | ||||
|   if (sibling && | ||||
|       clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor)) | ||||
|     { | ||||
|       clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling)); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_sort_depth_order (ClutterContainer *container) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv; | ||||
|  | ||||
|   priv->children = g_list_sort (priv->children, sort_by_depth); | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (container)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_container_iface_init (ClutterContainerIface *iface) | ||||
| { | ||||
|   iface->add = clutter_group_real_add; | ||||
|   iface->actor_added = clutter_group_real_actor_added; | ||||
|   iface->remove = clutter_group_real_remove; | ||||
|   iface->actor_removed = clutter_group_real_actor_removed; | ||||
|   iface->raise = clutter_group_real_raise; | ||||
|   iface->lower = clutter_group_real_lower; | ||||
|   iface->sort_depth_order = clutter_group_real_sort_depth_order; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_paint (ClutterActor        *actor, | ||||
|                           ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|  | ||||
|   CLUTTER_NOTE (PAINT, "ClutterGroup paint enter '%s'", | ||||
|                 _clutter_actor_get_debug_name (actor)); | ||||
|  | ||||
|   g_list_foreach (priv->children, (GFunc) clutter_actor_paint, paint_context); | ||||
|  | ||||
|   CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'", | ||||
|                 _clutter_actor_get_debug_name (actor)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_pick (ClutterActor       *actor, | ||||
|                          ClutterPickContext *pick_context) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|  | ||||
|   /* Chain up so we get a bounding box pained (if we are reactive) */ | ||||
|   CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick_context); | ||||
|  | ||||
|   g_list_foreach (priv->children, (GFunc) clutter_actor_pick, pick_context); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_get_preferred_width (ClutterActor *actor, | ||||
|                                         gfloat        for_height, | ||||
|                                         gfloat       *min_width, | ||||
|                                         gfloat       *natural_width) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|  | ||||
|   clutter_layout_manager_get_preferred_width (priv->layout, | ||||
|                                               CLUTTER_CONTAINER (actor), | ||||
|                                               for_height, | ||||
|                                               min_width, natural_width); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_get_preferred_height (ClutterActor *actor, | ||||
|                                          gfloat        for_width, | ||||
|                                          gfloat       *min_height, | ||||
|                                          gfloat       *natural_height) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|  | ||||
|   clutter_layout_manager_get_preferred_height (priv->layout, | ||||
|                                                CLUTTER_CONTAINER (actor), | ||||
|                                                for_width, | ||||
|                                                min_height, natural_height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_allocate (ClutterActor           *actor, | ||||
|                              const ClutterActorBox  *allocation) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|   ClutterActorClass *klass; | ||||
|  | ||||
|   klass = CLUTTER_ACTOR_CLASS (clutter_group_parent_class); | ||||
|   klass->allocate (actor, allocation); | ||||
|  | ||||
|   if (priv->children == NULL) | ||||
|     return; | ||||
|  | ||||
|   clutter_layout_manager_allocate (priv->layout, | ||||
|                                    CLUTTER_CONTAINER (actor), | ||||
|                                    allocation); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_dispose (GObject *object) | ||||
| { | ||||
|   ClutterGroup *self = CLUTTER_GROUP (object); | ||||
|   ClutterGroupPrivate *priv = self->priv; | ||||
|  | ||||
|   /* Note: we are careful to consider that destroying children could | ||||
|    * have the side-effect of destroying other children so | ||||
|    * priv->children may be modified during clutter_actor_destroy. */ | ||||
|   while (priv->children != NULL) | ||||
|     { | ||||
|       ClutterActor *child = priv->children->data; | ||||
|       priv->children = g_list_delete_link (priv->children, priv->children); | ||||
|       clutter_actor_destroy (child); | ||||
|     } | ||||
|  | ||||
|   if (priv->layout) | ||||
|     { | ||||
|       clutter_layout_manager_set_container (priv->layout, NULL); | ||||
|       g_object_unref (priv->layout); | ||||
|       priv->layout = NULL; | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_show_all (ClutterActor *self) | ||||
| { | ||||
|   ClutterActorIter iter; | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, self); | ||||
|   while (clutter_actor_iter_next (&iter, &actor)) | ||||
|     clutter_actor_show (actor); | ||||
|  | ||||
|   clutter_actor_show (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_real_hide_all (ClutterActor *actor) | ||||
| { | ||||
|   ClutterActorIter iter; | ||||
|  | ||||
|   clutter_actor_hide (actor); | ||||
|  | ||||
|   clutter_actor_iter_init (&iter, actor); | ||||
|   while (clutter_actor_iter_next (&iter, &actor)) | ||||
|     clutter_actor_hide (actor); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_group_real_get_paint_volume (ClutterActor       *actor, | ||||
|                                      ClutterPaintVolume *volume) | ||||
| { | ||||
|   ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv; | ||||
|   GList *l; | ||||
|  | ||||
|   if (priv->children == NULL) | ||||
|     return TRUE; | ||||
|  | ||||
|   for (l = priv->children; l != NULL; l = l->next) | ||||
|     { | ||||
|       ClutterActor *child = l->data; | ||||
|       const ClutterPaintVolume *child_volume; | ||||
|  | ||||
|       /* This gets the paint volume of the child transformed into the | ||||
|        * group's coordinate space... */ | ||||
|       child_volume = clutter_actor_get_transformed_paint_volume (child, actor); | ||||
|       if (!child_volume) | ||||
|         return FALSE; | ||||
|  | ||||
|       clutter_paint_volume_union (volume, child_volume); | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_class_init (ClutterGroupClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|  | ||||
|   actor_class->get_preferred_width = clutter_group_real_get_preferred_width; | ||||
|   actor_class->get_preferred_height = clutter_group_real_get_preferred_height; | ||||
|   actor_class->allocate = clutter_group_real_allocate; | ||||
|   actor_class->paint = clutter_group_real_paint; | ||||
|   actor_class->pick = clutter_group_real_pick; | ||||
|   actor_class->show_all = clutter_group_real_show_all; | ||||
|   actor_class->hide_all = clutter_group_real_hide_all; | ||||
|   actor_class->get_paint_volume = clutter_group_real_get_paint_volume; | ||||
|  | ||||
|   gobject_class->dispose = clutter_group_dispose; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_group_init (ClutterGroup *self) | ||||
| { | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (self); | ||||
|  | ||||
|   self->priv = clutter_group_get_instance_private (self); | ||||
|  | ||||
|   /* turn on some optimization | ||||
|    * | ||||
|    * XXX - these so-called "optimizations" are insane and should have never | ||||
|    * been used. they introduce some weird behaviour that breaks invariants | ||||
|    * and have to be explicitly worked around. | ||||
|    * | ||||
|    * this flag was set by the ClutterFixedLayout, but since that layout | ||||
|    * manager is now the default for ClutterActor, we set the flag explicitly | ||||
|    * here, to avoid breaking perfectly working actors overriding the | ||||
|    * allocate() virtual function. | ||||
|    * | ||||
|    * also, we keep this flag here so that it can die once we get rid of | ||||
|    * ClutterGroup. | ||||
|    */ | ||||
|   clutter_actor_set_flags (actor, CLUTTER_ACTOR_NO_LAYOUT); | ||||
|  | ||||
|   self->priv->layout = clutter_fixed_layout_new (); | ||||
|   g_object_ref_sink (self->priv->layout); | ||||
|  | ||||
|   clutter_actor_set_layout_manager (actor, self->priv->layout); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_group_new: | ||||
|  * | ||||
|  * Create a new  #ClutterGroup. | ||||
|  * | ||||
|  * Return value: the newly created #ClutterGroup actor | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_new() instead. | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_group_new (void) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_GROUP, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_group_remove_all: | ||||
|  * @self: A #ClutterGroup | ||||
|  * | ||||
|  * Removes all children actors from the #ClutterGroup. | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_remove_all_children() instead. | ||||
|  */ | ||||
| void | ||||
| clutter_group_remove_all (ClutterGroup *self) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_GROUP (self)); | ||||
|  | ||||
|   clutter_actor_remove_all_children (CLUTTER_ACTOR (self)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_group_get_n_children: | ||||
|  * @self: A #ClutterGroup | ||||
|  * | ||||
|  * Gets the number of actors held in the group. | ||||
|  * | ||||
|  * Return value: The number of child actors held in the group. | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_get_n_children() instead. | ||||
|  */ | ||||
| gint | ||||
| clutter_group_get_n_children (ClutterGroup *self) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0); | ||||
|  | ||||
|   return clutter_actor_get_n_children (CLUTTER_ACTOR (self)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_group_get_nth_child: | ||||
|  * @self: A #ClutterGroup | ||||
|  * @index_: the position of the requested actor. | ||||
|  * | ||||
|  * Gets a groups child held at @index_ in stack. | ||||
|  * | ||||
|  * Return value: (transfer none): A Clutter actor, or %NULL if | ||||
|  *   @index_ is invalid. | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_get_child_at_index() instead. | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_group_get_nth_child (ClutterGroup *self, | ||||
| 			     gint          index_) | ||||
| { | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL); | ||||
|  | ||||
|   actor = CLUTTER_ACTOR (self); | ||||
|   g_return_val_if_fail (index_ <= clutter_actor_get_n_children (actor), NULL); | ||||
|  | ||||
|   return clutter_actor_get_child_at_index (actor, index_); | ||||
| } | ||||
							
								
								
									
										62
									
								
								clutter/clutter/deprecated/clutter-group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								clutter/clutter/deprecated/clutter-group.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2011 Intel Corp | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __CLUTTER_GROUP_DEPRECATED_H__ | ||||
| #define __CLUTTER_GROUP_DEPRECATED_H__ | ||||
|  | ||||
| #include <clutter/clutter-types.h> | ||||
| #include <clutter/clutter-group.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_new) | ||||
| ClutterActor *  clutter_group_new               (void); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_child_at_index) | ||||
| ClutterActor *  clutter_group_get_nth_child     (ClutterGroup *self, | ||||
|                                                  gint          index_); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_n_children) | ||||
| gint            clutter_group_get_n_children    (ClutterGroup *self); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_remove_all_children) | ||||
| void            clutter_group_remove_all        (ClutterGroup *self); | ||||
|  | ||||
| #ifndef CLUTTER_DISABLE_DEPRECATED | ||||
|  | ||||
| /* for Mr. Mallum only */ | ||||
| #define clutter_group_add(group,actor)                  G_STMT_START {  \ | ||||
|   ClutterActor *_actor = (ClutterActor *) (actor);                      \ | ||||
|   if (CLUTTER_IS_GROUP ((group)) && CLUTTER_IS_ACTOR ((_actor)))        \ | ||||
|     {                                                                   \ | ||||
|       ClutterContainer *_container = (ClutterContainer *) (group);      \ | ||||
|       clutter_container_add_actor (_container, _actor);                 \ | ||||
|     }                                                   } G_STMT_END | ||||
|  | ||||
| #endif /* CLUTTER_DISABLE_DEPRECATED */ | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_GROUP_DEPRECATED_H__ */ | ||||
							
								
								
									
										626
									
								
								clutter/clutter/deprecated/clutter-rectangle.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										626
									
								
								clutter/clutter/deprecated/clutter-rectangle.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,626 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By Matthew Allum  <mallum@openedhand.com> | ||||
|  * | ||||
|  * 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, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:clutter-rectangle | ||||
|  * @short_description: An actor that displays a simple rectangle. | ||||
|  * | ||||
|  * #ClutterRectangle is a #ClutterActor which draws a simple filled rectangle. | ||||
|  * | ||||
|  * #ClutterRectangle is deprecated since Clutter 1.10. If you want an actor | ||||
|  * painting a solid color, you can replace it with #ClutterActor and set the | ||||
|  * #ClutterActor:background-color property to the desired #ClutterColor. If | ||||
|  * you are drawing more complex shapes, use #ClutterCanvas to draw using the | ||||
|  * Cairo 2D API instead. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #define CLUTTER_DISABLE_DEPRECATION_WARNINGS | ||||
| #include "deprecated/clutter-rectangle.h" | ||||
| #include "deprecated/clutter-actor.h" | ||||
|  | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-color.h" | ||||
| #include "clutter-debug.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| #include "cogl/cogl.h" | ||||
|  | ||||
| struct _ClutterRectanglePrivate | ||||
| { | ||||
|   ClutterColor color; | ||||
|   ClutterColor border_color; | ||||
|  | ||||
|   guint border_width; | ||||
|  | ||||
|   guint has_border : 1; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_COLOR, | ||||
|   PROP_BORDER_COLOR, | ||||
|   PROP_BORDER_WIDTH, | ||||
|   PROP_HAS_BORDER | ||||
|  | ||||
|   /* FIXME: Add gradient, rounded corner props etc */ | ||||
| }; | ||||
|  | ||||
| static const ClutterColor default_color        = { 255, 255, 255, 255 }; | ||||
| static const ClutterColor default_border_color = {   0,   0,   0, 255 }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR) | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_paint (ClutterActor        *self, | ||||
|                          ClutterPaintContext *paint_context) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE (self)->priv; | ||||
|   CoglFramebuffer *framebuffer = | ||||
|     clutter_paint_context_get_framebuffer (paint_context); | ||||
|   static CoglPipeline *default_color_pipeline = NULL; | ||||
|   CoglPipeline *content_pipeline; | ||||
|   ClutterActorBox alloc; | ||||
|   CoglColor color; | ||||
|   guint8 tmp_alpha; | ||||
|  | ||||
|   CLUTTER_NOTE (PAINT, | ||||
|                 "painting rect '%s'", | ||||
| 		clutter_actor_get_name (self) ? clutter_actor_get_name (self) | ||||
|                                               : "unknown"); | ||||
|   clutter_actor_get_allocation_box (self, &alloc); | ||||
|  | ||||
|   if (G_UNLIKELY (default_color_pipeline == NULL)) | ||||
|     { | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       default_color_pipeline = cogl_pipeline_new (ctx); | ||||
|     } | ||||
|  | ||||
|   g_assert (default_color_pipeline != NULL); | ||||
|   content_pipeline = cogl_pipeline_copy (default_color_pipeline); | ||||
|  | ||||
|   /* compute the composited opacity of the actor taking into | ||||
|    * account the opacity of the color set by the user | ||||
|    */ | ||||
|   tmp_alpha = clutter_actor_get_paint_opacity (self) | ||||
|             * priv->color.alpha | ||||
|             / 255; | ||||
|  | ||||
|   cogl_color_init_from_4ub (&color, | ||||
|                             priv->color.red, | ||||
|                             priv->color.green, | ||||
|                             priv->color.blue, | ||||
|                             tmp_alpha); | ||||
|   cogl_color_premultiply (&color); | ||||
|   cogl_pipeline_set_color (content_pipeline, &color); | ||||
|  | ||||
|   if (priv->has_border) | ||||
|     { | ||||
|       CoglPipeline *border_pipeline; | ||||
|  | ||||
|       border_pipeline = cogl_pipeline_copy (default_color_pipeline); | ||||
|  | ||||
|       tmp_alpha = clutter_actor_get_paint_opacity (self) | ||||
|                 * priv->border_color.alpha | ||||
|                 / 255; | ||||
|  | ||||
|       cogl_color_init_from_4ub (&color, | ||||
|                                 priv->border_color.red, | ||||
|                                 priv->border_color.green, | ||||
|                                 priv->border_color.blue, | ||||
|                                 tmp_alpha); | ||||
|       cogl_color_premultiply (&color); | ||||
|       cogl_pipeline_set_color (border_pipeline, &color); | ||||
|  | ||||
|       /* We paint the border and the content only if the rectangle | ||||
|        * is big enough to show them | ||||
|        */ | ||||
|       if ((priv->border_width * 2) < clutter_actor_box_get_width (&alloc) && | ||||
|           (priv->border_width * 2) < clutter_actor_box_get_height (&alloc)) | ||||
|         { | ||||
|           /* paint the border. this sucks, but it's the only way to make a border */ | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            border_pipeline, | ||||
|                                            priv->border_width, 0, | ||||
|                                            clutter_actor_box_get_width (&alloc), | ||||
|                                            priv->border_width); | ||||
|  | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            border_pipeline, | ||||
|                                            clutter_actor_box_get_width (&alloc) - priv->border_width, | ||||
|                                            priv->border_width, | ||||
|                                            clutter_actor_box_get_width (&alloc), | ||||
|                                            clutter_actor_box_get_height (&alloc)); | ||||
|  | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            border_pipeline, | ||||
|                                            0, clutter_actor_box_get_height (&alloc) - priv->border_width, | ||||
|                                            clutter_actor_box_get_width (&alloc) - priv->border_width, | ||||
|                                            clutter_actor_box_get_height (&alloc)); | ||||
|  | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            border_pipeline, | ||||
|                                            0, 0, | ||||
|                                            priv->border_width, | ||||
|                                            clutter_actor_box_get_height (&alloc) - priv->border_width); | ||||
|  | ||||
|           /* now paint the rectangle */ | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            content_pipeline, | ||||
|                                            priv->border_width, priv->border_width, | ||||
|                                            clutter_actor_box_get_width (&alloc) - priv->border_width, | ||||
|                                            clutter_actor_box_get_height (&alloc) - priv->border_width); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           /* Otherwise, we draw a rectangle with the same color | ||||
|            * as the border, since we can only fit that into the | ||||
|            * allocation. | ||||
|            */ | ||||
|           cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                            border_pipeline, | ||||
|                                            0, 0, | ||||
|                                            clutter_actor_box_get_width (&alloc), | ||||
|                                            clutter_actor_box_get_height (&alloc)); | ||||
|         } | ||||
|  | ||||
|       cogl_object_unref (border_pipeline); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                        content_pipeline, | ||||
|                                        0, 0, | ||||
|                                        clutter_actor_box_get_width (&alloc), | ||||
|                                        clutter_actor_box_get_height (&alloc)); | ||||
|     } | ||||
|  | ||||
|   cogl_object_unref (content_pipeline); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_rectangle_get_paint_volume (ClutterActor       *self, | ||||
|                                     ClutterPaintVolume *volume) | ||||
| { | ||||
|   return _clutter_actor_set_default_paint_volume (self, | ||||
|                                                   CLUTTER_TYPE_RECTANGLE, | ||||
|                                                   volume); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_rectangle_has_overlaps (ClutterActor *self) | ||||
| { | ||||
|   /* Rectangles never need an offscreen redirect because there are | ||||
|      never any overlapping primitives */ | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_set_property (GObject      *object, | ||||
| 				guint         prop_id, | ||||
| 				const GValue *value, | ||||
| 				GParamSpec   *pspec) | ||||
| { | ||||
|   ClutterRectangle *rectangle = CLUTTER_RECTANGLE(object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_COLOR: | ||||
|       clutter_rectangle_set_color (rectangle, clutter_value_get_color (value)); | ||||
|       break; | ||||
|     case PROP_BORDER_COLOR: | ||||
|       clutter_rectangle_set_border_color (rectangle, | ||||
|                                           clutter_value_get_color (value)); | ||||
|       break; | ||||
|     case PROP_BORDER_WIDTH: | ||||
|       clutter_rectangle_set_border_width (rectangle, | ||||
|                                           g_value_get_uint (value)); | ||||
|       break; | ||||
|     case PROP_HAS_BORDER: | ||||
|       rectangle->priv->has_border = g_value_get_boolean (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_get_property (GObject    *object, | ||||
| 				guint       prop_id, | ||||
| 				GValue     *value, | ||||
| 				GParamSpec *pspec) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE(object)->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_COLOR: | ||||
|       clutter_value_set_color (value, &priv->color); | ||||
|       break; | ||||
|     case PROP_BORDER_COLOR: | ||||
|       clutter_value_set_color (value, &priv->border_color); | ||||
|       break; | ||||
|     case PROP_BORDER_WIDTH: | ||||
|       g_value_set_uint (value, priv->border_width); | ||||
|       break; | ||||
|     case PROP_HAS_BORDER: | ||||
|       g_value_set_boolean (value, priv->has_border); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_finalize (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (clutter_rectangle_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_dispose (GObject *object) | ||||
| { | ||||
|   G_OBJECT_CLASS (clutter_rectangle_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_class_init (ClutterRectangleClass *klass) | ||||
| { | ||||
|   GObjectClass      *gobject_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec        *pspec; | ||||
|  | ||||
|   actor_class->paint            = clutter_rectangle_paint; | ||||
|   actor_class->get_paint_volume = clutter_rectangle_get_paint_volume; | ||||
|   actor_class->has_overlaps     = clutter_rectangle_has_overlaps; | ||||
|  | ||||
|   gobject_class->finalize     = clutter_rectangle_finalize; | ||||
|   gobject_class->dispose      = clutter_rectangle_dispose; | ||||
|   gobject_class->set_property = clutter_rectangle_set_property; | ||||
|   gobject_class->get_property = clutter_rectangle_get_property; | ||||
|  | ||||
|   /** | ||||
|    * ClutterRectangle:color: | ||||
|    * | ||||
|    * The color of the rectangle. | ||||
|    */ | ||||
|   pspec = clutter_param_spec_color ("color", | ||||
|                                     P_("Color"), | ||||
|                                     P_("The color of the rectangle"), | ||||
|                                     &default_color, | ||||
|                                     CLUTTER_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_COLOR, pspec); | ||||
|  | ||||
|   /** | ||||
|    * ClutterRectangle:border-color: | ||||
|    * | ||||
|    * The color of the border of the rectangle. | ||||
|    * | ||||
|    * Since: 0.2 | ||||
|    */ | ||||
|   pspec = clutter_param_spec_color ("border-color", | ||||
|                                     P_("Border Color"), | ||||
|                                     P_("The color of the border of the rectangle"), | ||||
|                                     &default_border_color, | ||||
|                                     CLUTTER_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_BORDER_COLOR, pspec); | ||||
|  | ||||
|   /** | ||||
|    * ClutterRectangle:border-width: | ||||
|    * | ||||
|    * The width of the border of the rectangle, in pixels. | ||||
|    * | ||||
|    * Since: 0.2 | ||||
|    */ | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_BORDER_WIDTH, | ||||
|                                    g_param_spec_uint ("border-width", | ||||
|                                                       P_("Border Width"), | ||||
|                                                       P_("The width of the border of the rectangle"), | ||||
|                                                       0, G_MAXUINT, | ||||
|                                                       0, | ||||
|                                                       CLUTTER_PARAM_READWRITE)); | ||||
|   /** | ||||
|    * ClutterRectangle:has-border: | ||||
|    * | ||||
|    * Whether the #ClutterRectangle should be displayed with a border. | ||||
|    * | ||||
|    * Since: 0.2 | ||||
|    */ | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_HAS_BORDER, | ||||
|                                    g_param_spec_boolean ("has-border", | ||||
|                                                          P_("Has Border"), | ||||
|                                                          P_("Whether the rectangle should have a border"), | ||||
|                                                          FALSE, | ||||
|                                                          CLUTTER_PARAM_READWRITE)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_rectangle_init (ClutterRectangle *self) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   self->priv = priv = clutter_rectangle_get_instance_private (self); | ||||
|  | ||||
|   priv->color = default_color; | ||||
|   priv->border_color = default_border_color; | ||||
|  | ||||
|   priv->border_width = 0; | ||||
|  | ||||
|   priv->has_border = FALSE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_new: | ||||
|  * | ||||
|  * Creates a new #ClutterActor with a rectangular shape. | ||||
|  * | ||||
|  * Return value: a new #ClutterRectangle | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_new() instead | ||||
|  */ | ||||
| ClutterActor* | ||||
| clutter_rectangle_new (void) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_RECTANGLE, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_new_with_color: | ||||
|  * @color: a #ClutterColor | ||||
|  * | ||||
|  * Creates a new #ClutterActor with a rectangular shape | ||||
|  * and of the given @color. | ||||
|  * | ||||
|  * Return value: a new #ClutterRectangle | ||||
|  * | ||||
|  * Deprecated: 1.10: Use clutter_actor_new() and | ||||
|  *   clutter_actor_set_background_color() instead | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_rectangle_new_with_color (const ClutterColor *color) | ||||
| { | ||||
|   return g_object_new (CLUTTER_TYPE_RECTANGLE, | ||||
| 		       "color", color, | ||||
| 		       NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_get_color: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * @color: (out caller-allocates): return location for a #ClutterColor | ||||
|  * | ||||
|  * Retrieves the color of @rectangle. | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and clutter_actor_get_background_color() | ||||
|  *   instead | ||||
|  */ | ||||
| void | ||||
| clutter_rectangle_get_color (ClutterRectangle *rectangle, | ||||
| 			     ClutterColor     *color) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); | ||||
|   g_return_if_fail (color != NULL); | ||||
|  | ||||
|   priv = rectangle->priv; | ||||
|  | ||||
|   color->red = priv->color.red; | ||||
|   color->green = priv->color.green; | ||||
|   color->blue = priv->color.blue; | ||||
|   color->alpha = priv->color.alpha; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_set_color: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * @color: a #ClutterColor | ||||
|  * | ||||
|  * Sets the color of @rectangle. | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and clutter_actor_set_background_color() | ||||
|  *   instead | ||||
|  */ | ||||
| void | ||||
| clutter_rectangle_set_color (ClutterRectangle   *rectangle, | ||||
| 			     const ClutterColor *color) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); | ||||
|   g_return_if_fail (color != NULL); | ||||
|  | ||||
|   g_object_ref (rectangle); | ||||
|  | ||||
|   priv = rectangle->priv; | ||||
|  | ||||
|   priv->color.red = color->red; | ||||
|   priv->color.green = color->green; | ||||
|   priv->color.blue = color->blue; | ||||
|   priv->color.alpha = color->alpha; | ||||
|  | ||||
| #if 0 | ||||
|   /* FIXME - appears to be causing border to always get drawn */ | ||||
|   if (clutter_color_equal (&priv->color, &priv->border_color)) | ||||
|     priv->has_border = FALSE; | ||||
|   else | ||||
|     priv->has_border = TRUE; | ||||
| #endif | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); | ||||
|  | ||||
|   g_object_notify (G_OBJECT (rectangle), "color"); | ||||
|   g_object_notify (G_OBJECT (rectangle), "has-border"); | ||||
|   g_object_unref (rectangle); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_get_border_width: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * | ||||
|  * Gets the width (in pixels) of the border used by @rectangle | ||||
|  * | ||||
|  * Return value: the border's width | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content | ||||
|  *   to draw the border using Cairo | ||||
|  */ | ||||
| guint | ||||
| clutter_rectangle_get_border_width (ClutterRectangle *rectangle) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_RECTANGLE (rectangle), 0); | ||||
|  | ||||
|   return rectangle->priv->border_width; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_set_border_width: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * @width: the width of the border | ||||
|  * | ||||
|  * Sets the width (in pixel) of the border used by @rectangle. | ||||
|  * A @width of 0 will unset the border. | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content | ||||
|  *   to draw the border using Cairo | ||||
|  */ | ||||
| void | ||||
| clutter_rectangle_set_border_width (ClutterRectangle *rectangle, | ||||
|                                     guint             width) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); | ||||
|   priv = rectangle->priv; | ||||
|  | ||||
|   if (priv->border_width != width) | ||||
|     { | ||||
|       g_object_ref (rectangle); | ||||
|  | ||||
|       priv->border_width = width; | ||||
|  | ||||
|       if (priv->border_width != 0) | ||||
|         priv->has_border = TRUE; | ||||
|       else | ||||
|         priv->has_border = FALSE; | ||||
|  | ||||
|       clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (rectangle), "border-width"); | ||||
|       g_object_notify (G_OBJECT (rectangle), "has-border"); | ||||
|       g_object_unref (rectangle); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_get_border_color: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * @color: (out caller-allocates): return location for a #ClutterColor | ||||
|  * | ||||
|  * Gets the color of the border used by @rectangle and places | ||||
|  * it into @color. | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw | ||||
|  *   the border with Cairo | ||||
|  */ | ||||
| void | ||||
| clutter_rectangle_get_border_color (ClutterRectangle *rectangle, | ||||
|                                     ClutterColor     *color) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); | ||||
|   g_return_if_fail (color != NULL); | ||||
|  | ||||
|   priv = rectangle->priv; | ||||
|  | ||||
|   color->red = priv->border_color.red; | ||||
|   color->green = priv->border_color.green; | ||||
|   color->blue = priv->border_color.blue; | ||||
|   color->alpha = priv->border_color.alpha; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_rectangle_set_border_color: | ||||
|  * @rectangle: a #ClutterRectangle | ||||
|  * @color: the color of the border | ||||
|  * | ||||
|  * Sets the color of the border used by @rectangle using @color | ||||
|  * | ||||
|  * Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw | ||||
|  *   the border with Cairo | ||||
|  */ | ||||
| void | ||||
| clutter_rectangle_set_border_color (ClutterRectangle   *rectangle, | ||||
|                                     const ClutterColor *color) | ||||
| { | ||||
|   ClutterRectanglePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle)); | ||||
|   g_return_if_fail (color != NULL); | ||||
|  | ||||
|   priv = rectangle->priv; | ||||
|  | ||||
|   if (priv->border_color.red != color->red || | ||||
|       priv->border_color.green != color->green || | ||||
|       priv->border_color.blue != color->blue || | ||||
|       priv->border_color.alpha != color->alpha) | ||||
|     { | ||||
|       g_object_ref (rectangle); | ||||
|  | ||||
|       priv->border_color.red = color->red; | ||||
|       priv->border_color.green = color->green; | ||||
|       priv->border_color.blue = color->blue; | ||||
|       priv->border_color.alpha = color->alpha; | ||||
|  | ||||
|       if (clutter_color_equal (&priv->color, &priv->border_color)) | ||||
|         priv->has_border = FALSE; | ||||
|       else | ||||
|         priv->has_border = TRUE; | ||||
|  | ||||
|       clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle)); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (rectangle), "border-color"); | ||||
|       g_object_notify (G_OBJECT (rectangle), "has-border"); | ||||
|       g_object_unref (rectangle); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										117
									
								
								clutter/clutter/deprecated/clutter-rectangle.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								clutter/clutter/deprecated/clutter-rectangle.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Authored By Matthew Allum  <mallum@openedhand.com> | ||||
|  * | ||||
|  * 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, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __CLUTTER_RECTANGLE_H__ | ||||
| #define __CLUTTER_RECTANGLE_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter-actor.h> | ||||
| #include <clutter/clutter-color.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_TYPE_RECTANGLE                  (clutter_rectangle_get_type()) | ||||
| #define CLUTTER_RECTANGLE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangle)) | ||||
| #define CLUTTER_RECTANGLE_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass)) | ||||
| #define CLUTTER_IS_RECTANGLE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_RECTANGLE)) | ||||
| #define CLUTTER_IS_RECTANGLE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_RECTANGLE)) | ||||
| #define CLUTTER_RECTANGLE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass)) | ||||
|  | ||||
| typedef struct _ClutterRectangle        ClutterRectangle; | ||||
| typedef struct _ClutterRectangleClass   ClutterRectangleClass; | ||||
| typedef struct _ClutterRectanglePrivate ClutterRectanglePrivate; | ||||
|  | ||||
| /** | ||||
|  * ClutterRectangle: | ||||
|  * | ||||
|  * The #ClutterRectangle structure contains only private data | ||||
|  * and should be accessed using the provided API | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  */ | ||||
| struct _ClutterRectangle | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor           parent; | ||||
|  | ||||
|   ClutterRectanglePrivate *priv; | ||||
| };  | ||||
|  | ||||
| /** | ||||
|  * ClutterRectangleClass: | ||||
|  * | ||||
|  * The #ClutterRectangleClass structure contains only private data | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  */ | ||||
| struct _ClutterRectangleClass  | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /* padding for future expansion */ | ||||
|   void (*_clutter_rectangle1) (void); | ||||
|   void (*_clutter_rectangle2) (void); | ||||
|   void (*_clutter_rectangle3) (void); | ||||
|   void (*_clutter_rectangle4) (void); | ||||
| }; | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| GType clutter_rectangle_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_new) | ||||
| ClutterActor *clutter_rectangle_new              (void); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_new) | ||||
| ClutterActor *clutter_rectangle_new_with_color   (const ClutterColor *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color) | ||||
| void          clutter_rectangle_get_color        (ClutterRectangle   *rectangle, | ||||
|                                                   ClutterColor       *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color) | ||||
| void          clutter_rectangle_set_color        (ClutterRectangle   *rectangle, | ||||
| 						  const ClutterColor *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| guint         clutter_rectangle_get_border_width (ClutterRectangle   *rectangle); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void          clutter_rectangle_set_border_width (ClutterRectangle   *rectangle, | ||||
|                                                   guint               width); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void          clutter_rectangle_get_border_color (ClutterRectangle   *rectangle, | ||||
|                                                   ClutterColor       *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void          clutter_rectangle_set_border_color (ClutterRectangle   *rectangle, | ||||
|                                                   const ClutterColor *color); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_RECTANGLE_H__ */ | ||||
							
								
								
									
										91
									
								
								clutter/clutter/deprecated/clutter-stage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								clutter/clutter/deprecated/clutter-stage.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2011 Intel Corp | ||||
|  * | ||||
|  * 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/>. | ||||
|  */ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #ifndef __CLUTTER_STAGE_DEPRECATED_H__ | ||||
| #define __CLUTTER_STAGE_DEPRECATED_H__ | ||||
|  | ||||
| #include <clutter/clutter-types.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #ifndef CLUTTER_DISABLE_DEPRECATED | ||||
|  | ||||
| /** | ||||
|  * CLUTTER_STAGE_WIDTH: | ||||
|  * | ||||
|  * Macro that evaluates to the width of the default stage | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.2: Use clutter_actor_get_width() instead | ||||
|  */ | ||||
| #define CLUTTER_STAGE_WIDTH()           (clutter_actor_get_width (clutter_stage_get_default ())) | ||||
|  | ||||
| /** | ||||
|  * CLUTTER_STAGE_HEIGHT: | ||||
|  * | ||||
|  * Macro that evaluates to the height of the default stage | ||||
|  * | ||||
|  * Since: 0.2 | ||||
|  * | ||||
|  * Deprecated: 1.2: use clutter_actor_get_height() instead | ||||
|  */ | ||||
| #define CLUTTER_STAGE_HEIGHT()          (clutter_actor_get_height (clutter_stage_get_default ())) | ||||
|  | ||||
| /* Commodity macro, for mallum only */ | ||||
| #define clutter_stage_add(stage,actor)                  G_STMT_START {  \ | ||||
|   if (CLUTTER_IS_STAGE ((stage)) && CLUTTER_IS_ACTOR ((actor)))         \ | ||||
|     {                                                                   \ | ||||
|       ClutterContainer *_container = (ClutterContainer *) (stage);      \ | ||||
|       ClutterActor *_actor = (ClutterActor *) (actor);                  \ | ||||
|       clutter_container_add_actor (_container, _actor);                 \ | ||||
|     }                                                   } G_STMT_END | ||||
|  | ||||
| #endif /* CLUTTER_DISABLE_DEPRECATED */ | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_stage_new) | ||||
| ClutterActor *  clutter_stage_get_default       (void); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| gboolean        clutter_stage_is_default        (ClutterStage       *stage); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_queue_redraw) | ||||
| void            clutter_stage_queue_redraw      (ClutterStage       *stage); | ||||
|  | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color) | ||||
| void            clutter_stage_set_color         (ClutterStage       *stage, | ||||
|                                                  const ClutterColor *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color) | ||||
| void            clutter_stage_get_color         (ClutterStage       *stage, | ||||
|                                                  ClutterColor       *color); | ||||
|  | ||||
| CLUTTER_DEPRECATED | ||||
| void            clutter_stage_ensure_current    (ClutterStage       *stage); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_DEPRECATED_H__ */ | ||||
| @@ -26,8 +26,15 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_timeline_new_for_actor) | ||||
| ClutterTimeline * clutter_timeline_new (guint duration_ms); | ||||
| CLUTTER_DEPRECATED_FOR(clutter_timeline_new) | ||||
| ClutterTimeline *               clutter_timeline_clone                  (ClutterTimeline          *timeline); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_timeline_set_repeat_count) | ||||
| void                            clutter_timeline_set_loop               (ClutterTimeline          *timeline, | ||||
|                                                                          gboolean                  loop); | ||||
|  | ||||
| CLUTTER_DEPRECATED_FOR(clutter_timeline_get_repeat_count) | ||||
| gboolean                        clutter_timeline_get_loop               (ClutterTimeline          *timeline); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -36,9 +36,9 @@ clutter_headers = [ | ||||
|   'clutter-feature.h', | ||||
|   'clutter-fixed-layout.h', | ||||
|   'clutter-flow-layout.h', | ||||
|   'clutter-frame-clock.h', | ||||
|   'clutter-gesture-action.h', | ||||
|   'clutter-grid-layout.h', | ||||
|   'clutter-group.h', | ||||
|   'clutter-image.h', | ||||
|   'clutter-input-device.h', | ||||
|   'clutter-input-device-tool.h', | ||||
| @@ -123,7 +123,6 @@ clutter_sources = [ | ||||
|   'clutter-fixed-layout.c', | ||||
|   'clutter-flatten-effect.c', | ||||
|   'clutter-flow-layout.c', | ||||
|   'clutter-frame-clock.c', | ||||
|   'clutter-gesture-action.c', | ||||
|   'clutter-graphene.c', | ||||
|   'clutter-grid-layout.c', | ||||
| @@ -141,6 +140,8 @@ clutter_sources = [ | ||||
|   'clutter-layout-manager.c', | ||||
|   'clutter-layout-meta.c', | ||||
|   'clutter-main.c', | ||||
|   'clutter-master-clock.c', | ||||
|   'clutter-master-clock-default.c', | ||||
|   'clutter-offscreen-effect.c', | ||||
|   'clutter-page-turn-effect.c', | ||||
|   'clutter-paint-context.c', | ||||
| @@ -198,6 +199,8 @@ clutter_private_headers = [ | ||||
|   'clutter-input-focus-private.h', | ||||
|   'clutter-input-method-private.h', | ||||
|   'clutter-input-pointer-a11y-private.h', | ||||
|   'clutter-master-clock.h', | ||||
|   'clutter-master-clock-default.h', | ||||
|   'clutter-offscreen-effect-private.h', | ||||
|   'clutter-paint-context-private.h', | ||||
|   'clutter-paint-node-private.h', | ||||
| @@ -209,7 +212,6 @@ clutter_private_headers = [ | ||||
|   'clutter-stage-private.h', | ||||
|   'clutter-stage-view-private.h', | ||||
|   'clutter-stage-window.h', | ||||
|   'clutter-timeline-private.h', | ||||
| ] | ||||
|  | ||||
| clutter_nonintrospected_sources = [ | ||||
| @@ -218,10 +220,21 @@ clutter_nonintrospected_sources = [ | ||||
| ] | ||||
|  | ||||
| clutter_deprecated_headers = [ | ||||
|   'deprecated/clutter-actor.h', | ||||
|   'deprecated/clutter-box.h', | ||||
|   'deprecated/clutter-container.h', | ||||
|   'deprecated/clutter-group.h', | ||||
|   'deprecated/clutter-rectangle.h', | ||||
|   'deprecated/clutter-stage.h', | ||||
|   'deprecated/clutter-timeline.h', | ||||
| ] | ||||
|  | ||||
| clutter_deprecated_sources = [ | ||||
|   'deprecated/clutter-box.c', | ||||
|   'deprecated/clutter-group.c', | ||||
|   'deprecated/clutter-rectangle.c', | ||||
| ] | ||||
|  | ||||
| clutter_backend_sources = [] | ||||
| clutter_backend_nonintrospected_sources = [ | ||||
|   'cogl/clutter-stage-cogl.c', | ||||
| @@ -275,8 +288,10 @@ cally_headers = [ | ||||
|     'cally/cally-actor.h', | ||||
|     'cally/cally-clone.h', | ||||
|     'cally/cally-factory.h', | ||||
|     'cally/cally-group.h', | ||||
|     'cally/cally.h', | ||||
|     'cally/cally-main.h', | ||||
|     'cally/cally-rectangle.h', | ||||
|     'cally/cally-root.h', | ||||
|     'cally/cally-stage.h', | ||||
|     'cally/cally-text.h', | ||||
| @@ -287,6 +302,8 @@ cally_sources = [ | ||||
|     'cally/cally-actor.c', | ||||
|     'cally/cally.c', | ||||
|     'cally/cally-clone.c', | ||||
|     'cally/cally-group.c', | ||||
|     'cally/cally-rectangle.c', | ||||
|     'cally/cally-root.c', | ||||
|     'cally/cally-stage.c', | ||||
|     'cally/cally-text.c', | ||||
| @@ -368,6 +385,7 @@ libmutter_clutter = shared_library(libmutter_clutter_name, | ||||
|     clutter_headers, | ||||
|     clutter_private_headers, | ||||
|     clutter_nonintrospected_sources, | ||||
|     clutter_deprecated_sources, | ||||
|     clutter_deprecated_headers, | ||||
|     clutter_backend_sources, | ||||
|     clutter_backend_nonintrospected_sources, | ||||
| @@ -413,6 +431,7 @@ if have_introspection | ||||
|       clutter_built_headers, | ||||
|       clutter_sources, | ||||
|       clutter_headers, | ||||
|       clutter_deprecated_sources, | ||||
|       clutter_deprecated_headers, | ||||
|     ], | ||||
|     nsversion: libmutter_api_version, | ||||
|   | ||||
| @@ -8,7 +8,6 @@ clutter_c_args = [ | ||||
|   '-DCLUTTER_SYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)), | ||||
|   '-DCLUTTER_COMPILATION=1', | ||||
|   '-DCOGL_DISABLE_DEPRECATION_WARNINGS', | ||||
|   '-DCOGL_ENABLE_MUTTER_API', | ||||
|   '-DG_LOG_DOMAIN="Clutter"', | ||||
| ] | ||||
|  | ||||
|   | ||||
| @@ -48,6 +48,7 @@ | ||||
| #include "cogl1-context.h" | ||||
| #include "cogl-sub-texture.h" | ||||
| #include "cogl-gtype-private.h" | ||||
| #include "driver/gl/cogl-pipeline-opengl-private.h" | ||||
| #include "driver/gl/cogl-texture-gl-private.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
|   | ||||
| @@ -51,6 +51,11 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| /* This isn't defined in the GLES headers */ | ||||
| #ifndef GL_UNSIGNED_INT | ||||
| #define GL_UNSIGNED_INT 0x1405 | ||||
| #endif | ||||
|  | ||||
| static void _cogl_attribute_free (CoglAttribute *attribute); | ||||
|  | ||||
| COGL_OBJECT_DEFINE (Attribute, attribute); | ||||
|   | ||||
| @@ -34,6 +34,7 @@ | ||||
|  | ||||
| #include "cogl-boxed-value.h" | ||||
| #include "cogl-context-private.h" | ||||
| #include "driver/gl/cogl-util-gl-private.h" | ||||
|  | ||||
| gboolean | ||||
| _cogl_boxed_value_equal (const CoglBoxedValue *bva, | ||||
| @@ -285,5 +286,90 @@ _cogl_boxed_value_set_uniform (CoglContext *ctx, | ||||
|                                GLint location, | ||||
|                                const CoglBoxedValue *value) | ||||
| { | ||||
|   ctx->driver_vtable->set_uniform (ctx, location, value); | ||||
|   switch (value->type) | ||||
|     { | ||||
|     case COGL_BOXED_NONE: | ||||
|       break; | ||||
|  | ||||
|     case COGL_BOXED_INT: | ||||
|       { | ||||
|         const int *ptr; | ||||
|  | ||||
|         if (value->count == 1) | ||||
|           ptr = value->v.int_value; | ||||
|         else | ||||
|           ptr = value->v.int_array; | ||||
|  | ||||
|         switch (value->size) | ||||
|           { | ||||
|           case 1: | ||||
|             GE( ctx, glUniform1iv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 2: | ||||
|             GE( ctx, glUniform2iv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 3: | ||||
|             GE( ctx, glUniform3iv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 4: | ||||
|             GE( ctx, glUniform4iv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case COGL_BOXED_FLOAT: | ||||
|       { | ||||
|         const float *ptr; | ||||
|  | ||||
|         if (value->count == 1) | ||||
|           ptr = value->v.float_value; | ||||
|         else | ||||
|           ptr = value->v.float_array; | ||||
|  | ||||
|         switch (value->size) | ||||
|           { | ||||
|           case 1: | ||||
|             GE( ctx, glUniform1fv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 2: | ||||
|             GE( ctx, glUniform2fv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 3: | ||||
|             GE( ctx, glUniform3fv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           case 4: | ||||
|             GE( ctx, glUniform4fv (location, value->count, ptr) ); | ||||
|             break; | ||||
|           } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case COGL_BOXED_MATRIX: | ||||
|       { | ||||
|         const float *ptr; | ||||
|  | ||||
|         if (value->count == 1) | ||||
|           ptr = value->v.matrix; | ||||
|         else | ||||
|           ptr = value->v.float_array; | ||||
|  | ||||
|         switch (value->size) | ||||
|           { | ||||
|           case 2: | ||||
|             GE( ctx, glUniformMatrix2fv (location, value->count, | ||||
|                                          FALSE, ptr) ); | ||||
|             break; | ||||
|           case 3: | ||||
|             GE( ctx, glUniformMatrix3fv (location, value->count, | ||||
|                                          FALSE, ptr) ); | ||||
|             break; | ||||
|           case 4: | ||||
|             GE( ctx, glUniformMatrix4fv (location, value->count, | ||||
|                                          FALSE, ptr) ); | ||||
|             break; | ||||
|           } | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -46,6 +46,7 @@ | ||||
| #include "cogl-pipeline-cache.h" | ||||
| #include "cogl-texture-2d.h" | ||||
| #include "cogl-sampler-cache-private.h" | ||||
| #include "cogl-gpu-info-private.h" | ||||
| #include "cogl-gl-header.h" | ||||
| #include "cogl-framebuffer-private.h" | ||||
| #include "cogl-onscreen-private.h" | ||||
| @@ -69,12 +70,14 @@ struct _CoglContext | ||||
|  | ||||
|   CoglDriver driver; | ||||
|  | ||||
|   /* Information about the GPU and driver which we can use to | ||||
|      determine certain workarounds */ | ||||
|   CoglGpuInfo gpu; | ||||
|  | ||||
|   /* vtables for the driver functions */ | ||||
|   const CoglDriverVtable *driver_vtable; | ||||
|   const CoglTextureDriver *texture_driver; | ||||
|  | ||||
|   void *driver_context; | ||||
|  | ||||
|   int glsl_major; | ||||
|   int glsl_minor; | ||||
|  | ||||
| @@ -121,6 +124,9 @@ struct _CoglContext | ||||
|  | ||||
|   CoglMatrixEntry identity_entry; | ||||
|  | ||||
|   GArray           *texture_units; | ||||
|   int               active_texture_unit; | ||||
|  | ||||
|   /* Only used for comparing other pipelines when reading pixels. */ | ||||
|   CoglPipeline     *opaque_color_pipeline; | ||||
|  | ||||
| @@ -309,4 +315,18 @@ void | ||||
| _cogl_context_set_current_modelview_entry (CoglContext *context, | ||||
|                                            CoglMatrixEntry *entry); | ||||
|  | ||||
| /* | ||||
|  * _cogl_context_get_gl_extensions: | ||||
|  * @context: A CoglContext | ||||
|  * | ||||
|  * Return value: a NULL-terminated array of strings representing the | ||||
|  *   supported extensions by the current driver. This array is owned | ||||
|  *   by the caller and should be freed with g_strfreev(). | ||||
|  */ | ||||
| char ** | ||||
| _cogl_context_get_gl_extensions (CoglContext *context); | ||||
|  | ||||
| const char * | ||||
| _cogl_context_get_gl_version (CoglContext *context); | ||||
|  | ||||
| #endif /* __COGL_CONTEXT_PRIVATE_H */ | ||||
|   | ||||
| @@ -45,12 +45,40 @@ | ||||
| #include "cogl-onscreen-private.h" | ||||
| #include "cogl-attribute-private.h" | ||||
| #include "cogl1-context.h" | ||||
| #include "cogl-gpu-info-private.h" | ||||
| #include "cogl-gtype-private.h" | ||||
| #include "winsys/cogl-winsys-private.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| /* These aren't defined in the GLES headers */ | ||||
| #ifndef GL_POINT_SPRITE | ||||
| #define GL_POINT_SPRITE 0x8861 | ||||
| #endif | ||||
|  | ||||
| #ifndef GL_NUM_EXTENSIONS | ||||
| #define GL_NUM_EXTENSIONS 0x821D | ||||
| #endif | ||||
|  | ||||
| /* This is a relatively new extension */ | ||||
| #ifndef GL_PURGED_CONTEXT_RESET_NV | ||||
| #define GL_PURGED_CONTEXT_RESET_NV 0x92BB | ||||
| #endif | ||||
|  | ||||
| /* These aren't defined in the GLES2 headers */ | ||||
| #ifndef GL_GUILTY_CONTEXT_RESET_ARB | ||||
| #define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 | ||||
| #endif | ||||
|  | ||||
| #ifndef GL_INNOCENT_CONTEXT_RESET_ARB | ||||
| #define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 | ||||
| #endif | ||||
|  | ||||
| #ifndef GL_UNKNOWN_CONTEXT_RESET_ARB | ||||
| #define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 | ||||
| #endif | ||||
|  | ||||
| static void _cogl_context_free (CoglContext *context); | ||||
|  | ||||
| COGL_OBJECT_DEFINE (Context, context); | ||||
| @@ -442,6 +470,94 @@ _cogl_context_set_current_modelview_entry (CoglContext *context, | ||||
|   context->current_modelview_entry = entry; | ||||
| } | ||||
|  | ||||
| char ** | ||||
| _cogl_context_get_gl_extensions (CoglContext *context) | ||||
| { | ||||
|   const char *env_disabled_extensions; | ||||
|   char **ret; | ||||
|  | ||||
|   /* In GL 3, querying GL_EXTENSIONS is deprecated so we have to build | ||||
|    * the array using glGetStringi instead */ | ||||
| #ifdef HAVE_COGL_GL | ||||
|   if (context->driver == COGL_DRIVER_GL3) | ||||
|     { | ||||
|       int num_extensions, i; | ||||
|  | ||||
|       context->glGetIntegerv (GL_NUM_EXTENSIONS, &num_extensions); | ||||
|  | ||||
|       ret = g_malloc (sizeof (char *) * (num_extensions + 1)); | ||||
|  | ||||
|       for (i = 0; i < num_extensions; i++) | ||||
|         { | ||||
|           const char *ext = | ||||
|             (const char *) context->glGetStringi (GL_EXTENSIONS, i); | ||||
|           ret[i] = g_strdup (ext); | ||||
|         } | ||||
|  | ||||
|       ret[num_extensions] = NULL; | ||||
|     } | ||||
|   else | ||||
| #endif | ||||
|     { | ||||
|       const char *all_extensions = | ||||
|         (const char *) context->glGetString (GL_EXTENSIONS); | ||||
|  | ||||
|       ret = g_strsplit (all_extensions, " ", 0 /* max tokens */); | ||||
|     } | ||||
|  | ||||
|   if ((env_disabled_extensions = g_getenv ("COGL_DISABLE_GL_EXTENSIONS"))) | ||||
|     { | ||||
|       char **split_env_disabled_extensions; | ||||
|       char **src, **dst; | ||||
|  | ||||
|       if (env_disabled_extensions) | ||||
|         split_env_disabled_extensions = | ||||
|           g_strsplit (env_disabled_extensions, | ||||
|                       ",", | ||||
|                       0 /* no max tokens */); | ||||
|       else | ||||
|         split_env_disabled_extensions = NULL; | ||||
|  | ||||
|       for (dst = ret, src = ret; | ||||
|            *src; | ||||
|            src++) | ||||
|         { | ||||
|           char **d; | ||||
|  | ||||
|           if (split_env_disabled_extensions) | ||||
|             for (d = split_env_disabled_extensions; *d; d++) | ||||
|               if (!strcmp (*src, *d)) | ||||
|                 goto disabled; | ||||
|  | ||||
|           *(dst++) = *src; | ||||
|           continue; | ||||
|  | ||||
|         disabled: | ||||
|           g_free (*src); | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       *dst = NULL; | ||||
|  | ||||
|       if (split_env_disabled_extensions) | ||||
|         g_strfreev (split_env_disabled_extensions); | ||||
|     } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| const char * | ||||
| _cogl_context_get_gl_version (CoglContext *context) | ||||
| { | ||||
|   const char *version_override; | ||||
|  | ||||
|   if ((version_override = g_getenv ("COGL_OVERRIDE_GL_VERSION"))) | ||||
|     return version_override; | ||||
|   else | ||||
|     return (const char *) context->glGetString (GL_VERSION); | ||||
|  | ||||
| } | ||||
|  | ||||
| int64_t | ||||
| cogl_get_clock_time (CoglContext *context) | ||||
| { | ||||
| @@ -456,11 +572,24 @@ cogl_get_clock_time (CoglContext *context) | ||||
| CoglGraphicsResetStatus | ||||
| cogl_get_graphics_reset_status (CoglContext *context) | ||||
| { | ||||
|   return context->driver_vtable->get_graphics_reset_status (context); | ||||
| } | ||||
|   if (!context->glGetGraphicsResetStatus) | ||||
|     return COGL_GRAPHICS_RESET_STATUS_NO_ERROR; | ||||
|  | ||||
| gboolean | ||||
| cogl_context_is_hardware_accelerated (CoglContext *context) | ||||
| { | ||||
|   return context->driver_vtable->is_hardware_accelerated (context); | ||||
|   switch (context->glGetGraphicsResetStatus ()) | ||||
|     { | ||||
|     case GL_GUILTY_CONTEXT_RESET_ARB: | ||||
|       return COGL_GRAPHICS_RESET_STATUS_GUILTY_CONTEXT_RESET; | ||||
|  | ||||
|     case GL_INNOCENT_CONTEXT_RESET_ARB: | ||||
|       return COGL_GRAPHICS_RESET_STATUS_INNOCENT_CONTEXT_RESET; | ||||
|  | ||||
|     case GL_UNKNOWN_CONTEXT_RESET_ARB: | ||||
|       return COGL_GRAPHICS_RESET_STATUS_UNKNOWN_CONTEXT_RESET; | ||||
|  | ||||
|     case GL_PURGED_CONTEXT_RESET_NV: | ||||
|       return COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET; | ||||
|  | ||||
|     default: | ||||
|       return COGL_GRAPHICS_RESET_STATUS_NO_ERROR; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -357,16 +357,6 @@ typedef enum _CoglGraphicsResetStatus | ||||
| COGL_EXPORT CoglGraphicsResetStatus | ||||
| cogl_get_graphics_reset_status (CoglContext *context); | ||||
|  | ||||
| /** | ||||
|  * cogl_context_is_hardware_accelerated: | ||||
|  * @context: a #CoglContext pointer | ||||
|  * | ||||
|  * Returns: %TRUE if the @context is hardware accelerated, or %FALSE if | ||||
|  * not. | ||||
|  */ | ||||
| COGL_EXPORT gboolean | ||||
| cogl_context_is_hardware_accelerated (CoglContext *context); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __COGL_CONTEXT_H__ */ | ||||
|   | ||||
| @@ -35,7 +35,6 @@ | ||||
| #include "cogl-offscreen.h" | ||||
| #include "cogl-framebuffer-private.h" | ||||
| #include "cogl-attribute-private.h" | ||||
| #include "cogl-sampler-cache-private.h" | ||||
|  | ||||
| typedef struct _CoglDriverVtable CoglDriverVtable; | ||||
|  | ||||
| @@ -47,12 +46,6 @@ struct _CoglDriverVtable | ||||
|   void | ||||
|   (* context_deinit) (CoglContext *context); | ||||
|  | ||||
|   gboolean | ||||
|   (* is_hardware_accelerated) (CoglContext *context); | ||||
|  | ||||
|   CoglGraphicsResetStatus | ||||
|   (* get_graphics_reset_status) (CoglContext *context); | ||||
|  | ||||
|   /* TODO: factor this out since this is OpenGL specific and | ||||
|    * so can be ignored by non-OpenGL drivers. */ | ||||
|   gboolean | ||||
| @@ -269,19 +262,6 @@ struct _CoglDriverVtable | ||||
|                        const void *data, | ||||
|                        unsigned int size, | ||||
|                        GError **error); | ||||
|  | ||||
|   void | ||||
|   (*sampler_init) (CoglContext *context, | ||||
|                    CoglSamplerCacheEntry *entry); | ||||
|  | ||||
|   void | ||||
|   (*sampler_free) (CoglContext *context, | ||||
|                    CoglSamplerCacheEntry *entry); | ||||
|  | ||||
|   void | ||||
|   (* set_uniform) (CoglContext *ctx, | ||||
|                    GLint location, | ||||
|                    const CoglBoxedValue *value); | ||||
| }; | ||||
|  | ||||
| #define COGL_DRIVER_ERROR (_cogl_driver_error_quark ()) | ||||
|   | ||||
| @@ -43,9 +43,10 @@ struct _CoglFrameInfo | ||||
|   float refresh_rate; | ||||
|  | ||||
|   int64_t global_frame_counter; | ||||
|  | ||||
|   CoglOutput *output; | ||||
| }; | ||||
|  | ||||
| COGL_EXPORT | ||||
| CoglFrameInfo *cogl_frame_info_new (int64_t global_frame_counter); | ||||
| CoglFrameInfo *_cogl_frame_info_new (void); | ||||
|  | ||||
| #endif /* __COGL_FRAME_INFO_PRIVATE_H */ | ||||
|   | ||||
| @@ -39,12 +39,11 @@ COGL_OBJECT_DEFINE (FrameInfo, frame_info); | ||||
| COGL_GTYPE_DEFINE_CLASS (FrameInfo, frame_info); | ||||
|  | ||||
| CoglFrameInfo * | ||||
| cogl_frame_info_new (int64_t global_frame_counter) | ||||
| _cogl_frame_info_new (void) | ||||
| { | ||||
|   CoglFrameInfo *info; | ||||
|  | ||||
|   info = g_slice_new0 (CoglFrameInfo); | ||||
|   info->global_frame_counter = global_frame_counter; | ||||
|  | ||||
|   return _cogl_frame_info_object_new (info); | ||||
| } | ||||
| @@ -73,6 +72,12 @@ cogl_frame_info_get_refresh_rate (CoglFrameInfo *info) | ||||
|   return info->refresh_rate; | ||||
| } | ||||
|  | ||||
| CoglOutput * | ||||
| cogl_frame_info_get_output (CoglFrameInfo *info) | ||||
| { | ||||
|   return info->output; | ||||
| } | ||||
|  | ||||
| int64_t | ||||
| cogl_frame_info_get_global_frame_counter (CoglFrameInfo *info) | ||||
| { | ||||
|   | ||||
| @@ -45,11 +45,6 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| /** | ||||
|  * CoglFrameInfo: | ||||
|  * | ||||
|  * Frame information. | ||||
|  */ | ||||
| typedef struct _CoglFrameInfo CoglFrameInfo; | ||||
| #define COGL_FRAME_INFO(X) ((CoglFrameInfo *)(X)) | ||||
|  | ||||
| @@ -131,6 +126,20 @@ int64_t cogl_frame_info_get_presentation_time (CoglFrameInfo *info); | ||||
| COGL_EXPORT | ||||
| float cogl_frame_info_get_refresh_rate (CoglFrameInfo *info); | ||||
|  | ||||
| /** | ||||
|  * cogl_frame_info_get_output: | ||||
|  * @info: a #CoglFrameInfo object | ||||
|  * | ||||
|  * Gets the #CoglOutput that the swapped frame was presented to. | ||||
|  * | ||||
|  * Return value: (transfer none): The #CoglOutput that the frame was | ||||
|  *        presented to, or %NULL if this could not be determined. | ||||
|  * Since: 1.14 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| COGL_EXPORT CoglOutput * | ||||
| cogl_frame_info_get_output (CoglFrameInfo *info); | ||||
|  | ||||
| /** | ||||
|  * cogl_frame_info_get_global_frame_counter: (skip) | ||||
|  */ | ||||
|   | ||||
							
								
								
									
										41
									
								
								cogl/cogl/cogl-glsl-shader-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								cogl/cogl/cogl-glsl-shader-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2012 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _COGL_GLSL_SHADER_PRIVATE_H_ | ||||
| #define _COGL_GLSL_SHADER_PRIVATE_H_ | ||||
|  | ||||
| void | ||||
| _cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx, | ||||
|                                                GLuint shader_gl_handle, | ||||
|                                                GLenum shader_gl_type, | ||||
|                                                CoglPipeline *pipeline, | ||||
|                                                GLsizei count_in, | ||||
|                                                const char **strings_in, | ||||
|                                                const GLint *lengths_in); | ||||
|  | ||||
| #endif /* _COGL_GLSL_SHADER_PRIVATE_H_ */ | ||||
							
								
								
									
										189
									
								
								cogl/cogl/cogl-glsl-shader.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								cogl/cogl/cogl-glsl-shader.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2012 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  * | ||||
|  * Authors: | ||||
|  *   Robert Bragg <robert@linux.intel.com> | ||||
|  *   Neil Roberts <neil@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| #include "cogl-config.h" | ||||
|  | ||||
| #include "cogl-context-private.h" | ||||
| #include "cogl-glsl-shader-private.h" | ||||
| #include "cogl-glsl-shader-boilerplate.h" | ||||
| #include "driver/gl/cogl-util-gl-private.h" | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| static gboolean | ||||
| add_layer_vertex_boilerplate_cb (CoglPipelineLayer *layer, | ||||
|                                  void *user_data) | ||||
| { | ||||
|   GString *layer_declarations = user_data; | ||||
|   int unit_index = _cogl_pipeline_layer_get_unit_index (layer); | ||||
|   g_string_append_printf (layer_declarations, | ||||
|                           "attribute vec4 cogl_tex_coord%d_in;\n" | ||||
|                           "#define cogl_texture_matrix%i cogl_texture_matrix[%i]\n" | ||||
|                           "#define cogl_tex_coord%i_out _cogl_tex_coord[%i]\n", | ||||
|                           layer->index, | ||||
|                           layer->index, | ||||
|                           unit_index, | ||||
|                           layer->index, | ||||
|                           unit_index); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| add_layer_fragment_boilerplate_cb (CoglPipelineLayer *layer, | ||||
|                                    void *user_data) | ||||
| { | ||||
|   GString *layer_declarations = user_data; | ||||
|   g_string_append_printf (layer_declarations, | ||||
|                           "#define cogl_tex_coord%i_in _cogl_tex_coord[%i]\n", | ||||
|                           layer->index, | ||||
|                           _cogl_pipeline_layer_get_unit_index (layer)); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| _cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx, | ||||
|                                                GLuint shader_gl_handle, | ||||
|                                                GLenum shader_gl_type, | ||||
|                                                CoglPipeline *pipeline, | ||||
|                                                GLsizei count_in, | ||||
|                                                const char **strings_in, | ||||
|                                                const GLint *lengths_in) | ||||
| { | ||||
|   const char *vertex_boilerplate; | ||||
|   const char *fragment_boilerplate; | ||||
|  | ||||
|   const char **strings = g_alloca (sizeof (char *) * (count_in + 4)); | ||||
|   GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 4)); | ||||
|   char *version_string; | ||||
|   int count = 0; | ||||
|  | ||||
|   int n_layers; | ||||
|  | ||||
|   vertex_boilerplate = _COGL_VERTEX_SHADER_BOILERPLATE; | ||||
|   fragment_boilerplate = _COGL_FRAGMENT_SHADER_BOILERPLATE; | ||||
|  | ||||
|   version_string = g_strdup_printf ("#version %i\n\n", | ||||
|                                     ctx->glsl_version_to_use); | ||||
|   strings[count] = version_string; | ||||
|   lengths[count++] = -1; | ||||
|  | ||||
|   if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL)) | ||||
|     { | ||||
|       static const char image_external_extension[] = | ||||
|         "#extension GL_OES_EGL_image_external : require\n"; | ||||
|       strings[count] = image_external_extension; | ||||
|       lengths[count++] = sizeof (image_external_extension) - 1; | ||||
|     } | ||||
|  | ||||
|   if (shader_gl_type == GL_VERTEX_SHADER) | ||||
|     { | ||||
|       strings[count] = vertex_boilerplate; | ||||
|       lengths[count++] = strlen (vertex_boilerplate); | ||||
|     } | ||||
|   else if (shader_gl_type == GL_FRAGMENT_SHADER) | ||||
|     { | ||||
|       strings[count] = fragment_boilerplate; | ||||
|       lengths[count++] = strlen (fragment_boilerplate); | ||||
|     } | ||||
|  | ||||
|   n_layers = cogl_pipeline_get_n_layers (pipeline); | ||||
|   if (n_layers) | ||||
|     { | ||||
|       GString *layer_declarations = ctx->codegen_boilerplate_buffer; | ||||
|       g_string_set_size (layer_declarations, 0); | ||||
|  | ||||
|       g_string_append_printf (layer_declarations, | ||||
|                               "varying vec4 _cogl_tex_coord[%d];\n", | ||||
|                               n_layers); | ||||
|  | ||||
|       if (shader_gl_type == GL_VERTEX_SHADER) | ||||
|         { | ||||
|           g_string_append_printf (layer_declarations, | ||||
|                                   "uniform mat4 cogl_texture_matrix[%d];\n", | ||||
|                                   n_layers); | ||||
|  | ||||
|           _cogl_pipeline_foreach_layer_internal (pipeline, | ||||
|                                                  add_layer_vertex_boilerplate_cb, | ||||
|                                                  layer_declarations); | ||||
|         } | ||||
|       else if (shader_gl_type == GL_FRAGMENT_SHADER) | ||||
|         { | ||||
|           _cogl_pipeline_foreach_layer_internal (pipeline, | ||||
|                                                  add_layer_fragment_boilerplate_cb, | ||||
|                                                  layer_declarations); | ||||
|         } | ||||
|  | ||||
|       strings[count] = layer_declarations->str; | ||||
|       lengths[count++] = -1; /* null terminated */ | ||||
|     } | ||||
|  | ||||
|   memcpy (strings + count, strings_in, sizeof (char *) * count_in); | ||||
|   if (lengths_in) | ||||
|     memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in); | ||||
|   else | ||||
|     { | ||||
|       int i; | ||||
|  | ||||
|       for (i = 0; i < count_in; i++) | ||||
|         lengths[count + i] = -1; /* null terminated */ | ||||
|     } | ||||
|   count += count_in; | ||||
|  | ||||
|   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE))) | ||||
|     { | ||||
|       GString *buf = g_string_new (NULL); | ||||
|       int i; | ||||
|  | ||||
|       g_string_append_printf (buf, | ||||
|                               "%s shader:\n", | ||||
|                               shader_gl_type == GL_VERTEX_SHADER ? | ||||
|                               "vertex" : "fragment"); | ||||
|       for (i = 0; i < count; i++) | ||||
|         if (lengths[i] != -1) | ||||
|           g_string_append_len (buf, strings[i], lengths[i]); | ||||
|         else | ||||
|           g_string_append (buf, strings[i]); | ||||
|  | ||||
|       g_message ("%s", buf->str); | ||||
|  | ||||
|       g_string_free (buf, TRUE); | ||||
|     } | ||||
|  | ||||
|   GE( ctx, glShaderSource (shader_gl_handle, count, | ||||
|                            (const char **) strings, lengths) ); | ||||
|  | ||||
|   g_free (version_string); | ||||
| } | ||||
							
								
								
									
										112
									
								
								cogl/cogl/cogl-gpu-info-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								cogl/cogl/cogl-gpu-info-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| /* | ||||
|  * Cogl | ||||
|  * | ||||
|  * A Low Level GPU Graphics and Utilities API | ||||
|  * | ||||
|  * Copyright (C) 2012 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  * | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef __COGL_GPU_INFO_PRIVATE_H | ||||
| #define __COGL_GPU_INFO_PRIVATE_H | ||||
|  | ||||
| #include "cogl-context.h" | ||||
|  | ||||
| typedef enum _CoglGpuInfoArchitectureFlag | ||||
| { | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE | ||||
| } CoglGpuInfoArchitectureFlag; | ||||
|  | ||||
| typedef enum _CoglGpuInfoArchitecture | ||||
| { | ||||
|   COGL_GPU_INFO_ARCHITECTURE_UNKNOWN, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_SGX, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_MALI, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE, | ||||
|   COGL_GPU_INFO_ARCHITECTURE_SWRAST | ||||
| } CoglGpuInfoArchitecture; | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   COGL_GPU_INFO_VENDOR_UNKNOWN, | ||||
|   COGL_GPU_INFO_VENDOR_INTEL, | ||||
|   COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES, | ||||
|   COGL_GPU_INFO_VENDOR_ARM, | ||||
|   COGL_GPU_INFO_VENDOR_QUALCOMM, | ||||
|   COGL_GPU_INFO_VENDOR_NVIDIA, | ||||
|   COGL_GPU_INFO_VENDOR_ATI, | ||||
|   COGL_GPU_INFO_VENDOR_MESA | ||||
| } CoglGpuInfoVendor; | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN, | ||||
|   COGL_GPU_INFO_DRIVER_PACKAGE_MESA | ||||
| } CoglGpuInfoDriverPackage; | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   COGL_GPU_INFO_DRIVER_STUB | ||||
| } CoglGpuInfoDriverBug; | ||||
|  | ||||
| typedef struct _CoglGpuInfoVersion CoglGpuInfoVersion; | ||||
|  | ||||
| typedef struct _CoglGpuInfo CoglGpuInfo; | ||||
|  | ||||
| struct _CoglGpuInfo | ||||
| { | ||||
|   CoglGpuInfoVendor vendor; | ||||
|   const char *vendor_name; | ||||
|  | ||||
|   CoglGpuInfoDriverPackage driver_package; | ||||
|   const char *driver_package_name; | ||||
|   int driver_package_version; | ||||
|  | ||||
|   CoglGpuInfoArchitecture architecture; | ||||
|   const char *architecture_name; | ||||
|   CoglGpuInfoArchitectureFlag architecture_flags; | ||||
|  | ||||
|   CoglGpuInfoDriverBug driver_bugs; | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * _cogl_gpu_info_init: | ||||
|  * @ctx: A #CoglContext | ||||
|  * @gpu: A return location for the GPU information | ||||
|  * | ||||
|  * Determines information about the GPU and driver from the given | ||||
|  * context. | ||||
|  */ | ||||
| void | ||||
| _cogl_gpu_info_init (CoglContext *ctx, | ||||
|                      CoglGpuInfo *gpu); | ||||
|  | ||||
| #endif /* __COGL_GPU_INFO_PRIVATE_H */ | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user