Compare commits
266 Commits
wip/smcv/c
...
3.37.3
Author | SHA1 | Date | |
---|---|---|---|
30d9d1968c | |||
65aa476414 | |||
03d177cf64 | |||
dfa235aa5d | |||
d722e59aac | |||
32dbcd9352 | |||
3a474556b8 | |||
249274c677 | |||
ae83a61e67 | |||
826573ccce | |||
dbff32ec5c | |||
2f1f47d257 | |||
06781985e4 | |||
5b0a7b3a33 | |||
1ecdaa646f | |||
2f4d50c723 | |||
4b8bb4608c | |||
aa34f6ad7c | |||
f9be670522 | |||
d77bcb9028 | |||
d29c8e290c | |||
e12ce70385 | |||
442f34b4de | |||
20becd782f | |||
feb8bfa0bf | |||
59a38fcb69 | |||
190e285c23 | |||
a9a9a0d1c5 | |||
57a2f7b4a3 | |||
1f895719b3 | |||
37326e4a32 | |||
8cff3b84f7 | |||
578c30792a | |||
9daec23033 | |||
5f729ea437 | |||
ae7cc0417f | |||
468bf81307 | |||
551101c65c | |||
110ed7ff8a | |||
2afe3e9223 | |||
de99dd7eb6 | |||
34be97d855 | |||
1de436684c | |||
847e89d31f | |||
f9eb140e62 | |||
3aff755048 | |||
2e358f3c43 | |||
c00a8e98a3 | |||
2a6e8bda8d | |||
31a3b1b4c5 | |||
ff65c95aee | |||
f086eafe57 | |||
bb73038a27 | |||
2b95ec40c6 | |||
203c20d7ad | |||
ff5f77f273 | |||
fc0b8f9d9c | |||
1e284c601c | |||
5e7ce7ea75 | |||
69d0ff4567 | |||
3944daf3c0 | |||
b45cea301e | |||
14dfe929f2 | |||
b9a52ecfdf | |||
feb444402e | |||
9ed463b488 | |||
33450700dc | |||
62f251574f | |||
59eebd6f6d | |||
ca82cde6dd | |||
9b054f4a1b | |||
f31a7acab5 | |||
a0d87662f7 | |||
c302f4d379 | |||
3c4efd13c1 | |||
9676db4dbf | |||
a132c8dc8e | |||
cae5b99537 | |||
6ffdfff9ee | |||
b18d4fc346 | |||
7e27fb6d56 | |||
8f96885af8 | |||
51ee41ee43 | |||
e743b36cfc | |||
96a108ed4e | |||
da633dcc52 | |||
86646679f1 | |||
df4eeff6f2 | |||
64304b0b68 | |||
c5159e3184 | |||
280429bac8 | |||
98df2dbd05 | |||
4a72ac0516 | |||
802b24a640 | |||
162aec7802 | |||
9823a0f6c9 | |||
b8524504f4 | |||
c1933cfd09 | |||
1142f06af5 | |||
bb4e87bf35 | |||
37256cb76b | |||
7f12099ead | |||
88141f1483 | |||
7146a6dddb | |||
dbce29a0ae | |||
031098a43d | |||
dc4cb562b7 | |||
2e086c74e7 | |||
e884ba7f39 | |||
2802d359e5 | |||
d54b10b366 | |||
d4993c4b22 | |||
ae49f89cf3 | |||
ce3e293a18 | |||
8d83dec044 | |||
d4953c77c3 | |||
237f277641 | |||
59e454f01e | |||
0b4cf9c65f | |||
82b710688b | |||
387a13f0ab | |||
e5542c3210 | |||
d85c3c1e94 | |||
d830d985c1 | |||
4c0aa2afca | |||
d6af59612c | |||
be59b514ca | |||
2e5b767c01 | |||
f511f94aa2 | |||
3187fe8ebc | |||
f5c8e0d96d | |||
c3d1320343 | |||
5c5dcd58b5 | |||
6ea0f8facc | |||
0c1e5b4ee5 | |||
ad50d2cfc4 | |||
1398c6dfa4 | |||
ab9f241cc5 | |||
1f5d6a01f5 | |||
ca79073014 | |||
0b6f5c6f55 | |||
e2c2a332e6 | |||
245977e525 | |||
e03c75bac7 | |||
4ff58cc63f | |||
462df7e61a | |||
1285619bcf | |||
d6f5ac5603 | |||
d133f94f8f | |||
e216d9c6ad | |||
79050004b0 | |||
e5ea8f5483 | |||
0ab1a9fa44 | |||
cb0cc42651 | |||
b36cfb5bdc | |||
7539de2320 | |||
8de91f1053 | |||
45c14f74b4 | |||
d4457d1f7f | |||
0ba15df57c | |||
e09ac67698 | |||
e6a93326bf | |||
fb474fb612 | |||
d12dc993d1 | |||
6414b8c45f | |||
19b467aa01 | |||
e089e53b24 | |||
bad1a7fd0c | |||
51a8193c16 | |||
94fb82137f | |||
49408e8f9f | |||
77d359cdc3 | |||
590b9b8c86 | |||
09078762ac | |||
352c2ec7b8 | |||
4b37c2e446 | |||
980ece9a4b | |||
1ce9e379d9 | |||
4a4f2d8264 | |||
4920b5064d | |||
26ddb07066 | |||
574b49ed95 | |||
6697b0d069 | |||
092c5304a9 | |||
c3fc6025b1 | |||
1406348be4 | |||
46e3d20057 | |||
9bcf1d0238 | |||
b69111d8e6 | |||
f71316c850 | |||
9186b6d6b0 | |||
55719afcbf | |||
e063947a16 | |||
a42eed0231 | |||
f4fd92d8e8 | |||
2ebd43cba9 | |||
2724f36527 | |||
569a183828 | |||
620dcf3364 | |||
eb9cd3857d | |||
0bfb995bff | |||
932340a989 | |||
ca0156e9a7 | |||
6d75b4fc53 | |||
6bd382ad23 | |||
a1b3d1a2a7 | |||
53f61f3778 | |||
74c0d9140c | |||
268336c21a | |||
49e983b06e | |||
0f97196d84 | |||
18c792d6f8 | |||
675a97d58e | |||
8127494e52 | |||
670f4f22fe | |||
e27d2702a8 | |||
dfe33897db | |||
90c20b185b | |||
4d7c8d68bc | |||
455de5d6d3 | |||
99c9f4c1fa | |||
dd32ff018a | |||
019643bad0 | |||
a031ac067e | |||
f712387325 | |||
1eaf9e5f63 | |||
7222bdde57 | |||
007d27fa40 | |||
01609de587 | |||
83ee122fad | |||
55302dbb38 | |||
7876018755 | |||
e3c332fa10 | |||
faa831f2f6 | |||
1a915f06cf | |||
6754195580 | |||
25f9406e69 | |||
9fc428f2e7 | |||
a05dd813da | |||
08b30d6fe2 | |||
84f55d38dd | |||
75b5e079cf | |||
d742f9331c | |||
420ca31f0b | |||
73da901cd3 | |||
dd16fac0c7 | |||
1b2af2891f | |||
050c21c24f | |||
7b45de941b | |||
8d84449941 | |||
f61d4b4e70 | |||
dcb42d3b25 | |||
59a2bff8e2 | |||
720360b07a | |||
9b39e37fee | |||
38104755a2 | |||
7abf0f1e2d | |||
0a37c32a72 | |||
9f121a211d | |||
c823b5ddba | |||
97175f8fa1 | |||
c5b1bdc0fe | |||
f8e2234ce5 | |||
38bbd9593b | |||
a3cc62c285 | |||
c3bf10d19a |
54
NEWS
54
NEWS
@ -1,3 +1,57 @@
|
||||
3.37.3
|
||||
======
|
||||
* Support custom keyboard layouts in $XDG_CONFIG_HOME/xkb [Peter; !936]
|
||||
* Optimize resource scale computation [Jonas D.; !1196, !1276, !1343]
|
||||
* Allow animating ClutterActor's content property [Georges; !1301]
|
||||
* Implement backgrounds as ClutterContent [Georges; !1302]
|
||||
* Add ClutterAlignContraint:pivot-point property [Jonas D.; !737]
|
||||
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
|
||||
* Do not paint textures of fully obscured windows [Robert; !1326]
|
||||
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
|
||||
* Fix remote desktop being broken without screencast session [Olivier; #1307]
|
||||
* Remove more long-deprecated Clutter APIs [Adam, Georges; !1194, !1332]
|
||||
* Drive each monitor by its own frame clock [Jonas Å.; !1285]
|
||||
* Fix copy/paste failures on X11 [Carlos; !1350]
|
||||
* Mipmap background texture rendering [Daniel; !1347]
|
||||
* Plugged memory leaks [Sebastian, Jonas D.; !1293, !1281, !1304]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Daniel, Corentin, Carlos,
|
||||
Sebastian, Michel, Robert, Florian; !1288, !1289, !1291, !1296, !1292, !1298,
|
||||
!1300, !1303, !1290, !1287, !1306, !1305, !1308, !1313, !1250, !1314, !1267,
|
||||
!1275, !1317, !1270, !1322, !1181, !1282, !1325, !1323, !1240, !1295, !1329,
|
||||
!1333, !1334, !1336, !1341, #1312, !1345, !1349, !1356, #873, !1310, !1357]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
|
||||
Peter Hutterer, Adam Jackson, Sebastian Keller, Robert Mader, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Corentin Noël, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
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]
|
||||
|
@ -1,147 +0,0 @@
|
||||
/* 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;
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/* 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__ */
|
@ -1,98 +0,0 @@
|
||||
/* 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;
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/* 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_GROUP,
|
||||
CALLY_TYPE_ACTOR,
|
||||
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-group.h>
|
||||
#include <cally/cally-actor.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -52,7 +52,7 @@ typedef struct _CallyStagePrivate CallyStagePrivate;
|
||||
struct _CallyStage
|
||||
{
|
||||
/*< private >*/
|
||||
CallyGroup parent;
|
||||
CallyActor parent;
|
||||
|
||||
CallyStagePrivate *priv;
|
||||
};
|
||||
@ -68,7 +68,7 @@ struct _CallyStage
|
||||
struct _CallyStageClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyGroupClass parent_class;
|
||||
CallyActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
gpointer _padding_dummy[16];
|
||||
|
@ -36,10 +36,8 @@
|
||||
#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"
|
||||
@ -52,10 +50,8 @@
|
||||
|
||||
/* 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)
|
||||
|
||||
/**
|
||||
@ -73,10 +69,8 @@ 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,9 +26,7 @@
|
||||
#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,6 +615,32 @@ 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,35 +110,12 @@ 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;
|
||||
@ -183,24 +160,15 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
|
||||
|
||||
struct _ClutterTransformInfo
|
||||
{
|
||||
/* rotation (angle and center) */
|
||||
/* rotation */
|
||||
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;
|
||||
@ -313,14 +281,18 @@ 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_queue_update_resource_scale_recursive (ClutterActor *actor);
|
||||
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
|
||||
|
||||
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
|
||||
float *resource_scale);
|
||||
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
|
||||
|
||||
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,11 +142,6 @@ 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
|
||||
@ -183,7 +178,10 @@ 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; it must chain up to the parent's implementation
|
||||
* 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
|
||||
* @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
|
||||
@ -226,7 +224,6 @@ 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);
|
||||
@ -302,6 +299,9 @@ 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 */
|
||||
@ -419,7 +419,9 @@ CLUTTER_EXPORT
|
||||
void clutter_actor_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self);
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self,
|
||||
float x,
|
||||
float y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_available_size (ClutterActor *self,
|
||||
gfloat x,
|
||||
@ -454,6 +456,10 @@ void clutter_actor_set_position
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_fixed_position (ClutterActor *self,
|
||||
float *x,
|
||||
float *y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_position (ClutterActor *self,
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
@ -593,8 +599,7 @@ gboolean clutter_actor_get_paint_box
|
||||
ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_resource_scale (ClutterActor *self,
|
||||
gfloat *resource_scale);
|
||||
float clutter_actor_get_resource_scale (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_overlaps (ClutterActor *self);
|
||||
@ -919,6 +924,15 @@ 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,6 +58,7 @@ struct _ClutterAlignConstraint
|
||||
ClutterActor *actor;
|
||||
ClutterActor *source;
|
||||
ClutterAlignAxis align_axis;
|
||||
graphene_point_t pivot;
|
||||
gfloat factor;
|
||||
};
|
||||
|
||||
@ -72,6 +73,7 @@ enum
|
||||
|
||||
PROP_SOURCE,
|
||||
PROP_ALIGN_AXIS,
|
||||
PROP_PIVOT_POINT,
|
||||
PROP_FACTOR,
|
||||
|
||||
PROP_LAST
|
||||
@ -84,12 +86,11 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
|
||||
CLUTTER_TYPE_CONSTRAINT);
|
||||
|
||||
static void
|
||||
source_position_changed (ClutterActor *actor,
|
||||
GParamSpec *pspec,
|
||||
ClutterAlignConstraint *align)
|
||||
source_queue_relayout (ClutterActor *actor,
|
||||
ClutterAlignConstraint *align)
|
||||
{
|
||||
if (align->actor != NULL)
|
||||
clutter_actor_queue_relayout (align->actor);
|
||||
_clutter_actor_queue_only_relayout (align->actor);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -134,35 +135,41 @@ clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
|
||||
gfloat source_width, source_height;
|
||||
gfloat actor_width, actor_height;
|
||||
gfloat source_x, source_y;
|
||||
gfloat offset_x_start, offset_y_start;
|
||||
gfloat pivot_x, pivot_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 = ((source_width - actor_width) * align->factor)
|
||||
+ source_x;
|
||||
allocation->x1 += offset_x_start + (source_width * align->factor);
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
break;
|
||||
|
||||
case CLUTTER_ALIGN_Y_AXIS:
|
||||
allocation->y1 = ((source_height - actor_height) * align->factor)
|
||||
+ source_y;
|
||||
allocation->y1 += offset_y_start + (source_height * align->factor);
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
|
||||
case CLUTTER_ALIGN_BOTH:
|
||||
allocation->x1 = ((source_width - actor_width) * align->factor)
|
||||
+ source_x;
|
||||
allocation->y1 = ((source_height - actor_height) * align->factor)
|
||||
+ source_y;
|
||||
allocation->x1 += offset_x_start + (source_width * align->factor);
|
||||
allocation->y1 += offset_y_start + (source_height * align->factor);
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
@ -186,7 +193,7 @@ clutter_align_constraint_dispose (GObject *gobject)
|
||||
G_CALLBACK (source_destroyed),
|
||||
align);
|
||||
g_signal_handlers_disconnect_by_func (align->source,
|
||||
G_CALLBACK (source_position_changed),
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
align->source = NULL;
|
||||
}
|
||||
@ -212,6 +219,10 @@ 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;
|
||||
@ -240,6 +251,16 @@ 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;
|
||||
@ -293,6 +314,30 @@ 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:
|
||||
*
|
||||
@ -325,6 +370,8 @@ 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;
|
||||
}
|
||||
|
||||
@ -402,15 +449,15 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
|
||||
G_CALLBACK (source_destroyed),
|
||||
align);
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_position_changed),
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
}
|
||||
|
||||
align->source = source;
|
||||
if (align->source != NULL)
|
||||
{
|
||||
g_signal_connect (align->source, "notify::allocation",
|
||||
G_CALLBACK (source_position_changed),
|
||||
g_signal_connect (align->source, "queue-relayout",
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
g_signal_connect (align->source, "destroy",
|
||||
G_CALLBACK (source_destroyed),
|
||||
@ -487,6 +534,60 @@ 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,6 +67,12 @@ 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,3 +194,25 @@ 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,6 +50,7 @@ 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
|
||||
*/
|
||||
@ -72,6 +73,7 @@ struct _ClutterAnimatableInterface
|
||||
ClutterInterval *interval,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
@ -92,6 +94,9 @@ 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,6 +53,8 @@ struct _ClutterBackend
|
||||
gfloat units_per_em;
|
||||
gint32 units_serial;
|
||||
|
||||
float fallback_resource_scale;
|
||||
|
||||
ClutterStageWindow *stage_window;
|
||||
|
||||
ClutterInputMethod *input_method;
|
||||
@ -134,6 +136,12 @@ 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,6 +601,8 @@ clutter_backend_init (ClutterBackend *self)
|
||||
self->units_serial = 1;
|
||||
|
||||
self->dummy_onscreen = NULL;
|
||||
|
||||
self->fallback_resource_scale = 1.f;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1031,3 +1033,16 @@ 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,12 +38,14 @@
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* // source
|
||||
* rect[0] = clutter_rectangle_new_with_color (&red_color);
|
||||
* rect[0] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[0], &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_rectangle_new_with_color (&green_color);
|
||||
* rect[1] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[1], &green_color);
|
||||
* clutter_actor_set_size (rect[1], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[1], 0);
|
||||
*
|
||||
@ -53,7 +55,8 @@
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
|
||||
*
|
||||
* // third rectangle
|
||||
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
|
||||
* rect[2] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[2], &blue_color);
|
||||
* clutter_actor_set_size (rect[2], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[2], 0);
|
||||
*
|
||||
@ -165,6 +168,9 @@ 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:
|
||||
|
@ -167,8 +167,10 @@ 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))
|
||||
@ -183,8 +185,22 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
||||
get_child_size (child, priv->orientation,
|
||||
for_size, &child_min, &child_nat);
|
||||
|
||||
minimum += child_min;
|
||||
natural += 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;
|
||||
}
|
||||
|
||||
if (n_children > 1)
|
||||
@ -315,6 +331,8 @@ 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)
|
||||
{
|
||||
|
@ -52,6 +52,8 @@
|
||||
struct _ClutterClonePrivate
|
||||
{
|
||||
ClutterActor *clone_source;
|
||||
float x_scale, y_scale;
|
||||
|
||||
gulong source_destroy_id;
|
||||
};
|
||||
|
||||
@ -122,8 +124,6 @@ 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,21 +134,7 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
|
||||
if (priv->clone_source == NULL)
|
||||
return;
|
||||
|
||||
/* 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);
|
||||
cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -244,6 +230,8 @@ 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);
|
||||
@ -257,7 +245,31 @@ clutter_clone_allocate (ClutterActor *self,
|
||||
*/
|
||||
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
|
||||
!clutter_actor_has_allocation (priv->clone_source))
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source);
|
||||
{
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
|
||||
}
|
||||
|
||||
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
|
||||
@ -364,6 +376,9 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,13 +3,7 @@
|
||||
|
||||
#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__
|
||||
|
||||
|
@ -1317,8 +1317,6 @@ 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().
|
||||
*
|
||||
@ -1328,7 +1326,6 @@ 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;
|
||||
|
||||
/**
|
||||
|
@ -139,7 +139,11 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
|
||||
child != NULL;
|
||||
child = clutter_actor_get_next_sibling (child))
|
||||
{
|
||||
clutter_actor_allocate_preferred_size (child);
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (child, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (child, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
550
clutter/clutter/clutter-frame-clock.c
Normal file
550
clutter/clutter/clutter-frame-clock.c
Normal file
@ -0,0 +1,550 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
87
clutter/clutter/clutter-frame-clock.h
Normal file
87
clutter/clutter/clutter-frame-clock.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 */
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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,20 +692,6 @@ _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,
|
||||
@ -815,7 +801,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;
|
||||
@ -850,7 +836,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);
|
||||
@ -1054,7 +1040,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);
|
||||
|
||||
@ -1085,22 +1071,33 @@ clutter_input_device_update (ClutterInputDevice *device,
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_pointer_actor:
|
||||
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
|
||||
* clutter_input_device_get_actor:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @sequence: (allow-none): an optional #ClutterEventSequence
|
||||
*
|
||||
* Retrieves the #ClutterActor underneath the pointer of @device
|
||||
* Retrieves the #ClutterActor underneath the pointer or touchpoint
|
||||
* of @device and @sequence.
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #ClutterActor or %NULL
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_input_device_get_pointer_actor (ClutterInputDevice *device)
|
||||
clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
|
||||
ClutterTouchInfo *info;
|
||||
|
||||
return device->cursor_actor;
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +92,8 @@ 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_pointer_actor (ClutterInputDevice *device);
|
||||
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
|
@ -32,8 +32,7 @@
|
||||
* 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. Clutter provides
|
||||
* a generic container using #ClutterLayoutManager called #ClutterBox.
|
||||
* layouting of its children to a #ClutterLayoutManager.
|
||||
*
|
||||
* Clutter provides some simple #ClutterLayoutManager sub-classes, like
|
||||
* #ClutterFlowLayout and #ClutterBinLayout.
|
||||
@ -97,7 +96,7 @@
|
||||
*
|
||||
* |[
|
||||
* {
|
||||
* "type" : "ClutterBox",
|
||||
* "type" : "ClutterActor",
|
||||
* "layout-manager" : { "type" : "ClutterGridLayout" },
|
||||
* "children" : [
|
||||
* {
|
||||
|
@ -61,7 +61,6 @@
|
||||
#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"
|
||||
@ -83,10 +82,6 @@
|
||||
|
||||
/* 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;
|
||||
@ -145,12 +140,6 @@ 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"
|
||||
|
||||
@ -519,11 +508,7 @@ clutter_main (void)
|
||||
main_loops = g_slist_prepend (main_loops, loop);
|
||||
|
||||
if (g_main_loop_is_running (main_loops->data))
|
||||
{
|
||||
_clutter_threads_release_lock ();
|
||||
g_main_loop_run (loop);
|
||||
_clutter_threads_acquire_lock ();
|
||||
}
|
||||
g_main_loop_run (loop);
|
||||
|
||||
main_loops = g_slist_remove (main_loops, loop);
|
||||
|
||||
@ -540,13 +525,9 @@ _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;
|
||||
}
|
||||
|
||||
@ -771,40 +752,6 @@ 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)
|
||||
{
|
||||
@ -814,8 +761,8 @@ _clutter_context_is_initialized (void)
|
||||
return ClutterCntx->is_initialized;
|
||||
}
|
||||
|
||||
static ClutterMainContext *
|
||||
clutter_context_get_default_unlocked (void)
|
||||
ClutterMainContext *
|
||||
_clutter_context_get_default (void)
|
||||
{
|
||||
if (G_UNLIKELY (ClutterCntx == NULL))
|
||||
{
|
||||
@ -846,20 +793,6 @@ clutter_context_get_default_unlocked (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,
|
||||
@ -2049,7 +1982,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
emit_touch_event (event, device);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_END)
|
||||
if (event->type == CLUTTER_TOUCH_END ||
|
||||
event->type == CLUTTER_TOUCH_CANCEL)
|
||||
_clutter_input_device_remove_event_sequence (device, event);
|
||||
|
||||
break;
|
||||
@ -2084,7 +2018,8 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
emit_touch_event (event, device);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_END)
|
||||
if (event->type == CLUTTER_TOUCH_END ||
|
||||
event->type == CLUTTER_TOUCH_CANCEL)
|
||||
_clutter_input_device_remove_event_sequence (device, event);
|
||||
|
||||
break;
|
||||
@ -2154,27 +2089,6 @@ _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)
|
||||
{
|
||||
@ -2189,9 +2103,6 @@ clutter_base_init (void)
|
||||
g_type_init ();
|
||||
#endif
|
||||
|
||||
/* initialise the Big Clutter Lock™ if necessary */
|
||||
clutter_threads_init_default ();
|
||||
|
||||
clutter_graphene_init ();
|
||||
}
|
||||
}
|
||||
@ -2259,9 +2170,7 @@ clutter_threads_remove_repaint_func (guint handle_id)
|
||||
|
||||
g_return_if_fail (handle_id > 0);
|
||||
|
||||
_clutter_context_lock ();
|
||||
|
||||
context = clutter_context_get_default_unlocked ();
|
||||
context = _clutter_context_get_default ();
|
||||
l = context->repaint_funcs;
|
||||
while (l != NULL)
|
||||
{
|
||||
@ -2284,8 +2193,6 @@ clutter_threads_remove_repaint_func (guint handle_id)
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_clutter_context_unlock ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2384,16 +2291,13 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
|
||||
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
_clutter_context_lock ();
|
||||
|
||||
context = clutter_context_get_default_unlocked ();
|
||||
context = _clutter_context_get_default ();
|
||||
|
||||
repaint_func = g_slice_new (ClutterRepaintFunction);
|
||||
|
||||
repaint_func->id = context->last_repaint_id++;
|
||||
|
||||
/* 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->flags = flags;
|
||||
repaint_func->func = func;
|
||||
repaint_func->data = data;
|
||||
repaint_func->notify = notify;
|
||||
@ -2401,15 +2305,6 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -1,618 +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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
@ -1,132 +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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,69 +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_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,6 +39,10 @@
|
||||
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));
|
||||
|
||||
@ -69,13 +73,7 @@ gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||
GError **error);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
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);
|
||||
void clutter_stage_clear_stage_views (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_view_assign_next_scanout (ClutterStageView *stage_view,
|
||||
|
@ -238,8 +238,8 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat target_width = -1, target_height = -1;
|
||||
CoglFramebuffer *framebuffer;
|
||||
gfloat resource_scale;
|
||||
gfloat ceiled_resource_scale;
|
||||
float resource_scale;
|
||||
float ceiled_resource_scale;
|
||||
graphene_point3d_t local_offset;
|
||||
gfloat old_viewport[4];
|
||||
|
||||
@ -254,17 +254,11 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
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 ();
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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
|
||||
@ -417,8 +411,9 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
|
||||
*/
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
|
||||
|
||||
if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
|
||||
resource_scale != 1.0f)
|
||||
resource_scale = clutter_actor_get_resource_scale (priv->actor);
|
||||
|
||||
if (resource_scale != 1.0f)
|
||||
{
|
||||
float paint_scale = 1.0f / resource_scale;
|
||||
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
|
||||
|
@ -1412,6 +1412,7 @@ clutter_layer_node_new (const CoglMatrix *projection,
|
||||
{
|
||||
ClutterLayerNode *res;
|
||||
CoglContext *context;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglTexture *texture;
|
||||
CoglColor color;
|
||||
|
||||
@ -1426,9 +1427,10 @@ clutter_layer_node_new (const CoglMatrix *projection,
|
||||
/* the texture backing the FBO */
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
texture = cogl_texture_2d_new_with_size (context,
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
tex_2d = cogl_texture_2d_new_with_size (context,
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture));
|
||||
|
@ -62,6 +62,7 @@
|
||||
#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)
|
||||
@ -136,7 +137,8 @@ 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,
|
||||
@ -156,14 +158,18 @@ 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)))
|
||||
@ -282,7 +288,10 @@ 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)
|
||||
{
|
||||
@ -293,7 +302,9 @@ 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))
|
||||
@ -304,17 +315,26 @@ 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 (duration);
|
||||
clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO);
|
||||
priv->deceleration_timeline = clutter_timeline_new_for_actor (pan_actor,
|
||||
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);
|
||||
@ -367,7 +387,8 @@ 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:
|
||||
@ -411,9 +432,11 @@ static void
|
||||
clutter_pan_action_constructed (GObject *gobject)
|
||||
{
|
||||
ClutterGestureAction *gesture;
|
||||
ClutterGestureTriggerEdge edge;
|
||||
|
||||
gesture = CLUTTER_GESTURE_ACTION (gobject);
|
||||
clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_AFTER);
|
||||
edge = CLUTTER_GESTURE_TRIGGER_EDGE_AFTER;
|
||||
clutter_gesture_action_set_threshold_trigger_edge (gesture, edge);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -440,9 +463,12 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@ -880,7 +906,9 @@ 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,7 +37,6 @@
|
||||
#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"
|
||||
@ -122,9 +121,6 @@ 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;
|
||||
|
||||
@ -177,11 +173,6 @@ 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);
|
||||
@ -316,6 +307,30 @@ 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,6 +278,26 @@ 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,8 +78,13 @@ 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_ONLY))
|
||||
if (!(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)))
|
||||
{
|
||||
unparsed = g_list_prepend (unparsed, pinfo);
|
||||
continue;
|
||||
|
@ -50,14 +50,14 @@
|
||||
* <informalexample><programlisting><![CDATA[
|
||||
* {
|
||||
* "id" : "red-button",
|
||||
* "type" : "ClutterRectangle",
|
||||
* "type" : "ClutterActor",
|
||||
* "width" : 100,
|
||||
* "height" : 100,
|
||||
* "color" : "#ff0000ff"
|
||||
* "background-color" : "#ff0000ff"
|
||||
* }
|
||||
* ]]></programlisting></informalexample>
|
||||
*
|
||||
* This will produce a red #ClutterRectangle, 100x100 pixels wide, and
|
||||
* This will produce a red #ClutterActor, 100x100 pixels wide, and
|
||||
* with a ClutterScript id of "red-button"; it can be retrieved by calling:
|
||||
*
|
||||
* |[
|
||||
|
@ -354,6 +354,17 @@ 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
|
||||
@ -370,7 +381,7 @@ clutter_seat_list_devices (ClutterSeat *seat)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL);
|
||||
|
||||
return CLUTTER_SEAT_GET_CLASS (seat)->list_devices (seat);
|
||||
return g_list_copy ((GList *)clutter_seat_peek_devices (seat));
|
||||
}
|
||||
|
||||
void
|
||||
@ -634,8 +645,8 @@ clutter_seat_create_virtual_device (ClutterSeat *seat,
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_seat_supported_virtual_device_types: (skip)
|
||||
*/
|
||||
* clutter_seat_get_supported_virtual_device_types: (skip)
|
||||
**/
|
||||
ClutterVirtualDeviceType
|
||||
clutter_seat_get_supported_virtual_device_types (ClutterSeat *seat)
|
||||
{
|
||||
@ -682,7 +693,6 @@ 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);
|
||||
|
||||
GList * (* list_devices) (ClutterSeat *seat);
|
||||
const GList * (* peek_devices) (ClutterSeat *seat);
|
||||
|
||||
void (* bell_notify) (ClutterSeat *seat);
|
||||
|
||||
@ -133,6 +133,7 @@ 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);
|
||||
|
||||
|
@ -40,7 +40,14 @@ void clutter_stage_paint_view (ClutterStage
|
||||
ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip);
|
||||
|
||||
void _clutter_stage_emit_after_paint (ClutterStage *stage);
|
||||
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);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_stage_set_window (ClutterStage *stage,
|
||||
@ -50,11 +57,6 @@ 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,
|
||||
@ -63,9 +65,12 @@ 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);
|
||||
gboolean _clutter_stage_needs_update (ClutterStage *stage);
|
||||
gboolean _clutter_stage_do_update (ClutterStage *stage);
|
||||
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);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_stage_queue_event (ClutterStage *stage,
|
||||
@ -74,8 +79,6 @@ 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,
|
||||
@ -130,17 +133,22 @@ 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,
|
||||
CoglFrameEvent frame_event,
|
||||
void clutter_stage_presented (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_stage_dequeue_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,6 +19,7 @@
|
||||
#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);
|
||||
@ -62,4 +63,12 @@ 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,8 +24,10 @@
|
||||
#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
|
||||
@ -33,11 +35,13 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_NAME,
|
||||
PROP_STAGE,
|
||||
PROP_LAYOUT,
|
||||
PROP_FRAMEBUFFER,
|
||||
PROP_OFFSCREEN,
|
||||
PROP_USE_SHADOWFB,
|
||||
PROP_SCALE,
|
||||
PROP_REFRESH_RATE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@ -48,6 +52,8 @@ typedef struct _ClutterStageViewPrivate
|
||||
{
|
||||
char *name;
|
||||
|
||||
ClutterStage *stage;
|
||||
|
||||
cairo_rectangle_int_t layout;
|
||||
float scale;
|
||||
CoglFramebuffer *framebuffer;
|
||||
@ -71,6 +77,9 @@ 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;
|
||||
@ -102,9 +111,9 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
if (priv->offscreen)
|
||||
return priv->offscreen;
|
||||
return COGL_FRAMEBUFFER (priv->offscreen);
|
||||
else if (priv->shadow.framebuffer)
|
||||
return priv->shadow.framebuffer;
|
||||
return COGL_FRAMEBUFFER (priv->shadow.framebuffer);
|
||||
else
|
||||
return priv->framebuffer;
|
||||
}
|
||||
@ -127,8 +136,9 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
||||
clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen);
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
|
||||
@ -137,7 +147,7 @@ clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0,
|
||||
cogl_offscreen_get_texture (framebuffer));
|
||||
cogl_offscreen_get_texture (offscreen));
|
||||
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
@ -158,7 +168,7 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
return;
|
||||
|
||||
priv->offscreen_pipeline =
|
||||
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
|
||||
clutter_stage_view_create_offscreen_pipeline (priv->offscreen);
|
||||
|
||||
if (view_class->setup_offscreen_blit_pipeline)
|
||||
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
|
||||
@ -192,7 +202,7 @@ clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view
|
||||
static void
|
||||
paint_transformed_framebuffer (ClutterStageView *view,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFramebuffer *src_framebuffer,
|
||||
CoglOffscreen *src_framebuffer,
|
||||
CoglFramebuffer *dst_framebuffer,
|
||||
const cairo_region_t *redraw_clip)
|
||||
{
|
||||
@ -432,10 +442,13 @@ 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,
|
||||
priv->shadow.framebuffer,
|
||||
shadowfb,
|
||||
redraw_clip);
|
||||
}
|
||||
else
|
||||
@ -508,7 +521,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 (priv->shadow.framebuffer);
|
||||
cogl_framebuffer_finish (COGL_FRAMEBUFFER (priv->shadow.framebuffer));
|
||||
|
||||
if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error))
|
||||
return NULL;
|
||||
@ -601,7 +614,7 @@ swap_dma_buf_framebuffer (ClutterStageView *view)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
int next_idx;
|
||||
CoglDmaBufHandle *next_dma_buf_handle;
|
||||
CoglOffscreen *next_framebuffer;
|
||||
CoglFramebuffer *next_framebuffer;
|
||||
|
||||
next_idx = ((priv->shadow.dma_buf.current_idx + 1) %
|
||||
G_N_ELEMENTS (priv->shadow.dma_buf.handles));
|
||||
@ -697,12 +710,13 @@ 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 (priv->shadow.framebuffer,
|
||||
if (!cogl_blit_framebuffer (shadowfb,
|
||||
priv->framebuffer,
|
||||
rect.x, rect.y,
|
||||
rect.x, rect.y,
|
||||
@ -754,7 +768,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
|
||||
|
||||
if (priv->offscreen)
|
||||
{
|
||||
callback (priv->offscreen, user_data);
|
||||
callback (COGL_FRAMEBUFFER (priv->offscreen), user_data);
|
||||
}
|
||||
else if (priv->shadow.framebuffer)
|
||||
{
|
||||
@ -773,7 +787,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
|
||||
}
|
||||
else
|
||||
{
|
||||
callback (priv->shadow.framebuffer, user_data);
|
||||
callback (COGL_FRAMEBUFFER (priv->shadow.framebuffer), user_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -988,6 +1002,154 @@ 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,
|
||||
@ -1003,6 +1165,9 @@ 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;
|
||||
@ -1018,6 +1183,9 @@ 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);
|
||||
}
|
||||
@ -1039,26 +1207,15 @@ 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:
|
||||
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
|
||||
clutter_stage_view_set_framebuffer (view, g_value_get_boxed (value));
|
||||
break;
|
||||
case PROP_OFFSCREEN:
|
||||
priv->offscreen = g_value_dup_boxed (value);
|
||||
@ -1069,6 +1226,9 @@ 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);
|
||||
}
|
||||
@ -1084,6 +1244,10 @@ 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);
|
||||
}
|
||||
|
||||
@ -1110,6 +1274,7 @@ 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);
|
||||
}
|
||||
@ -1123,6 +1288,7 @@ 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
|
||||
@ -1146,6 +1312,16 @@ 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",
|
||||
@ -1191,5 +1367,14 @@ 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,6 +27,7 @@
|
||||
#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
|
||||
@ -69,4 +70,7 @@ 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,81 +103,12 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window,
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_schedule_update (ClutterStageWindow *window,
|
||||
int sync_delay)
|
||||
_clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||
|
||||
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);
|
||||
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -44,12 +44,8 @@ struct _ClutterStageWindowInterface
|
||||
void (* get_geometry) (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *geometry);
|
||||
|
||||
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);
|
||||
void (* redraw_view) (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view);
|
||||
|
||||
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
|
||||
|
||||
@ -78,15 +74,12 @@ 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 (ClutterStageWindow *window);
|
||||
void _clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||
ClutterStageView *view);
|
||||
|
||||
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 >*/
|
||||
ClutterGroup parent_instance;
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterStagePrivate *priv;
|
||||
};
|
||||
@ -74,7 +74,7 @@ struct _ClutterStage
|
||||
struct _ClutterStageClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterGroupClass parent_class;
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
/* signals */
|
||||
@ -195,11 +195,10 @@ 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 (ClutterStage *stage);
|
||||
gboolean clutter_stage_is_redraw_queued_on_view (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
CLUTTER_EXPORT
|
||||
|
@ -187,9 +187,6 @@ 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;
|
||||
@ -598,9 +595,7 @@ ensure_effective_pango_scale_attribute (ClutterText *self)
|
||||
float resource_scale;
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale) ||
|
||||
resource_scale == 1.0)
|
||||
return;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
if (priv->effective_attrs != NULL)
|
||||
{
|
||||
@ -922,18 +917,6 @@ 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
|
||||
@ -1137,8 +1120,7 @@ maybe_create_text_layout_with_resource_scale (ClutterText *text,
|
||||
{
|
||||
float resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
|
||||
return NULL;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text));
|
||||
|
||||
return create_text_layout_with_scale (text,
|
||||
allocation_width,
|
||||
@ -1170,8 +1152,7 @@ clutter_text_coords_to_position (ClutterText *self,
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0);
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return 0;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
/* Take any offset due to scrolling into account, and normalize
|
||||
* the coordinates to PangoScale units
|
||||
@ -1299,8 +1280,7 @@ clutter_text_position_to_coords (ClutterText *self,
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE);
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return FALSE;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
ret = clutter_text_position_to_coords_internal (self, position,
|
||||
x, y, line_height);
|
||||
@ -1776,7 +1756,6 @@ 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 ());
|
||||
|
||||
@ -2641,8 +2620,7 @@ clutter_text_paint (ClutterActor *self,
|
||||
!clutter_text_should_draw_cursor (text))
|
||||
return;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
clutter_actor_box_scale (&alloc, resource_scale);
|
||||
clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height);
|
||||
@ -2874,8 +2852,7 @@ clutter_text_get_paint_volume (ClutterActor *self,
|
||||
if (!clutter_actor_has_allocation (self))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
return FALSE;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
_clutter_paint_volume_init_static (&priv->paint_volume, self);
|
||||
|
||||
@ -2932,8 +2909,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
|
||||
gfloat layout_width;
|
||||
gfloat resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
resource_scale = 1;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
layout = clutter_text_create_layout (text, -1, -1);
|
||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
||||
@ -2989,8 +2965,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
gfloat layout_height;
|
||||
gfloat resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
resource_scale = 1;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
if (priv->single_line_mode)
|
||||
for_width = -1;
|
||||
@ -3066,6 +3041,33 @@ 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)
|
||||
{
|
||||
@ -3814,6 +3816,8 @@ 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:
|
||||
@ -4621,11 +4625,6 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
33
clutter/clutter/clutter-timeline-private.h
Normal file
33
clutter/clutter/clutter-timeline-private.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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,22 +95,31 @@
|
||||
#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 "deprecated/clutter-timeline.h"
|
||||
#include "clutter-timeline-private.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 */
|
||||
@ -172,13 +181,14 @@ enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_LOOP,
|
||||
PROP_ACTOR,
|
||||
PROP_DELAY,
|
||||
PROP_DURATION,
|
||||
PROP_DIRECTION,
|
||||
PROP_AUTO_REVERSE,
|
||||
PROP_REPEAT_COUNT,
|
||||
PROP_PROGRESS_MODE,
|
||||
PROP_FRAME_CLOCK,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@ -199,6 +209,8 @@ 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,
|
||||
@ -290,21 +302,175 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
|
||||
g_hash_table_insert (priv->markers_by_name, marker->name, marker);
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_timeline_set_loop_internal (ClutterTimeline *timeline,
|
||||
gboolean loop)
|
||||
static void
|
||||
on_actor_destroyed (ClutterActor *actor,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
gint old_repeat_count;
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
old_repeat_count = timeline->priv->repeat_count;
|
||||
priv->actor = NULL;
|
||||
}
|
||||
|
||||
if (loop)
|
||||
clutter_timeline_set_repeat_count (timeline, -1);
|
||||
else
|
||||
clutter_timeline_set_repeat_count (timeline, 0);
|
||||
/**
|
||||
* 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 (old_repeat_count != timeline->priv->repeat_count)
|
||||
g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_LOOP]);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Scriptable */
|
||||
@ -448,8 +614,8 @@ clutter_timeline_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LOOP:
|
||||
clutter_timeline_set_loop_internal (timeline, g_value_get_boolean (value));
|
||||
case PROP_ACTOR:
|
||||
clutter_timeline_set_actor (timeline, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_DELAY:
|
||||
@ -476,6 +642,10 @@ 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;
|
||||
@ -493,8 +663,8 @@ clutter_timeline_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LOOP:
|
||||
g_value_set_boolean (value, priv->repeat_count != 0);
|
||||
case PROP_ACTOR:
|
||||
g_value_set_object (value, priv->actor);
|
||||
break;
|
||||
|
||||
case PROP_DELAY:
|
||||
@ -521,6 +691,10 @@ 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;
|
||||
@ -532,16 +706,14 @@ 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)
|
||||
{
|
||||
master_clock = _clutter_master_clock_get_default ();
|
||||
_clutter_master_clock_remove_timeline (master_clock, self);
|
||||
}
|
||||
maybe_remove_timeline (self);
|
||||
|
||||
g_clear_object (&priv->frame_clock);
|
||||
|
||||
G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object);
|
||||
}
|
||||
@ -556,6 +728,14 @@ 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);
|
||||
@ -573,24 +753,17 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
/**
|
||||
* ClutterTimeline:loop:
|
||||
* ClutterTimeline::actor:
|
||||
*
|
||||
* 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.
|
||||
* The actor the timeline is associated with. This will determine what frame
|
||||
* clock will drive it.
|
||||
*/
|
||||
obj_props[PROP_LOOP] =
|
||||
g_param_spec_boolean ("loop",
|
||||
P_("Loop"),
|
||||
P_("Should the timeline automatically restart"),
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
|
||||
|
||||
obj_props[PROP_ACTOR] =
|
||||
g_param_spec_object ("actor",
|
||||
P_("Actor"),
|
||||
P_("Associated ClutterActor"),
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
|
||||
/**
|
||||
* ClutterTimeline:delay:
|
||||
*
|
||||
@ -689,6 +862,18 @@ 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;
|
||||
@ -971,7 +1156,6 @@ set_is_playing (ClutterTimeline *timeline,
|
||||
gboolean is_playing)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
ClutterMasterClock *master_clock;
|
||||
|
||||
is_playing = !!is_playing;
|
||||
|
||||
@ -980,15 +1164,17 @@ 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;
|
||||
_clutter_master_clock_add_timeline (master_clock, timeline);
|
||||
|
||||
maybe_add_timeline (timeline);
|
||||
}
|
||||
else
|
||||
_clutter_master_clock_remove_timeline (master_clock, timeline);
|
||||
{
|
||||
maybe_remove_timeline (timeline);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1185,6 +1371,9 @@ 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,
|
||||
@ -1251,45 +1440,6 @@ 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
|
||||
@ -1405,49 +1555,11 @@ clutter_timeline_is_playing (ClutterTimeline *timeline)
|
||||
return timeline->priv->is_playing;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_clone:
|
||||
* @timeline: #ClutterTimeline to duplicate.
|
||||
*
|
||||
* 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
|
||||
* @duration_ms: Duration of the timeline in milliseconds
|
||||
*
|
||||
* Creates a new #ClutterTimeline with a duration of @msecs.
|
||||
* 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
|
||||
@ -1455,10 +1567,50 @@ clutter_timeline_clone (ClutterTimeline *timeline)
|
||||
* Since: 0.6
|
||||
*/
|
||||
ClutterTimeline *
|
||||
clutter_timeline_new (guint msecs)
|
||||
clutter_timeline_new (guint duration_ms)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_TIMELINE,
|
||||
"duration", msecs,
|
||||
"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,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@ -1724,7 +1876,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
|
||||
* master-clock generated signal of a different timeline, this code can
|
||||
* frame clock generated signal of a different timeline, this code can
|
||||
* still be reached.
|
||||
*/
|
||||
if (!priv->is_playing)
|
||||
@ -2542,3 +2694,32 @@ 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,7 +119,19 @@ CLUTTER_EXPORT
|
||||
GType clutter_timeline_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterTimeline * clutter_timeline_new (guint msecs);
|
||||
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);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_timeline_get_duration (ClutterTimeline *timeline);
|
||||
@ -221,6 +233,13 @@ 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,6 +43,7 @@
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-timeline-private.h"
|
||||
|
||||
struct _ClutterTransitionGroupPrivate
|
||||
{
|
||||
|
@ -364,6 +364,7 @@ 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));
|
||||
@ -383,6 +384,9 @@ 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,6 +57,7 @@ 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 */
|
||||
@ -174,6 +175,20 @@ 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
|
||||
@ -252,6 +267,9 @@ 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,6 +47,7 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-view-private.h"
|
||||
#include "cogl.h"
|
||||
|
||||
#define MAX_STACK_RECTS 256
|
||||
|
||||
@ -55,17 +56,25 @@ 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));
|
||||
|
||||
@ -77,67 +86,12 @@ 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)
|
||||
{
|
||||
@ -158,101 +112,14 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
|
||||
gint sync_delay)
|
||||
static int64_t
|
||||
clutter_stage_cogl_get_frame_counter (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
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;
|
||||
ClutterStageCoglPrivate *priv =
|
||||
_clutter_stage_cogl_get_instance_private (stage_cogl);
|
||||
|
||||
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;
|
||||
return priv->global_frame_counter;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
@ -355,12 +222,35 @@ 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);
|
||||
@ -369,6 +259,7 @@ 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);
|
||||
@ -383,6 +274,9 @@ 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)
|
||||
{
|
||||
@ -391,9 +285,8 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
onscreen);
|
||||
|
||||
cogl_onscreen_swap_region (onscreen,
|
||||
damage, n_rects);
|
||||
|
||||
return FALSE;
|
||||
damage, n_rects,
|
||||
frame_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -401,18 +294,35 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
onscreen);
|
||||
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen,
|
||||
damage, n_rects);
|
||||
|
||||
return TRUE;
|
||||
damage, n_rects,
|
||||
frame_info);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
return FALSE;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,11 +449,11 @@ is_buffer_age_enabled (void)
|
||||
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view)
|
||||
static void
|
||||
clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
|
||||
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
@ -551,7 +461,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
|
||||
cairo_rectangle_int_t view_rect;
|
||||
gboolean is_full_redraw;
|
||||
gboolean use_clipped_redraw;
|
||||
gboolean use_clipped_redraw = TRUE;
|
||||
gboolean can_blit_sub_buffer;
|
||||
gboolean has_buffer_age;
|
||||
gboolean swap_with_damage;
|
||||
@ -561,8 +471,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cairo_region_t *swap_region;
|
||||
float fb_scale;
|
||||
int fb_width, fb_height;
|
||||
int buffer_age;
|
||||
gboolean res;
|
||||
int buffer_age = 0;
|
||||
|
||||
clutter_stage_view_get_layout (view, &view_rect);
|
||||
fb_scale = clutter_stage_view_get_scale (view);
|
||||
@ -629,7 +538,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
redraw_clip = cairo_region_create_rectangle (&view_rect);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (!cairo_region_is_empty (fb_clip_region), FALSE);
|
||||
g_return_if_fail (!cairo_region_is_empty (fb_clip_region));
|
||||
|
||||
swap_with_damage = FALSE;
|
||||
if (has_buffer_age)
|
||||
@ -730,14 +639,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cairo_region_destroy (queued_redraw_clip);
|
||||
}
|
||||
|
||||
res = swap_framebuffer (stage_window,
|
||||
view,
|
||||
swap_region,
|
||||
swap_with_damage);
|
||||
swap_framebuffer (stage_window,
|
||||
view,
|
||||
swap_region,
|
||||
swap_with_damage);
|
||||
|
||||
cairo_region_destroy (swap_region);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -745,62 +652,34 @@ 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);
|
||||
cogl_onscreen_direct_scanout (onscreen, scanout);
|
||||
|
||||
frame_info = cogl_frame_info_new (priv->global_frame_counter);
|
||||
priv->global_frame_counter++;
|
||||
|
||||
cogl_onscreen_direct_scanout (onscreen, scanout, frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
gboolean swap_event = FALSE;
|
||||
GList *l;
|
||||
g_autoptr (CoglScanout) scanout = NULL;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -812,10 +691,8 @@ 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->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;
|
||||
iface->get_frame_counter = clutter_stage_cogl_get_frame_counter;
|
||||
iface->redraw_view = clutter_stage_cogl_redraw_view;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -856,10 +733,43 @@ _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;
|
||||
}
|
||||
|
||||
stage->update_time = -1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -869,6 +779,7 @@ 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);
|
||||
@ -881,6 +792,9 @@ 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,20 +41,6 @@ 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
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
@ -1,745 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
@ -1,554 +0,0 @@
|
||||
/*
|
||||
* 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_);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
@ -1,626 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* 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__ */
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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,15 +26,8 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
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);
|
||||
CLUTTER_DEPRECATED_FOR(clutter_timeline_new_for_actor)
|
||||
ClutterTimeline * clutter_timeline_new (guint duration_ms);
|
||||
|
||||
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,6 +123,7 @@ 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',
|
||||
@ -140,8 +141,6 @@ 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',
|
||||
@ -199,8 +198,6 @@ 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',
|
||||
@ -212,6 +209,7 @@ clutter_private_headers = [
|
||||
'clutter-stage-private.h',
|
||||
'clutter-stage-view-private.h',
|
||||
'clutter-stage-window.h',
|
||||
'clutter-timeline-private.h',
|
||||
]
|
||||
|
||||
clutter_nonintrospected_sources = [
|
||||
@ -220,21 +218,10 @@ 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',
|
||||
@ -288,10 +275,8 @@ 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',
|
||||
@ -302,8 +287,6 @@ 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',
|
||||
@ -385,7 +368,6 @@ 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,
|
||||
@ -431,7 +413,6 @@ if have_introspection
|
||||
clutter_built_headers,
|
||||
clutter_sources,
|
||||
clutter_headers,
|
||||
clutter_deprecated_sources,
|
||||
clutter_deprecated_headers,
|
||||
],
|
||||
nsversion: libmutter_api_version,
|
||||
|
@ -8,6 +8,7 @@ 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,7 +48,6 @@
|
||||
#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,11 +51,6 @@
|
||||
#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,7 +34,6 @@
|
||||
|
||||
#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,
|
||||
@ -286,90 +285,5 @@ _cogl_boxed_value_set_uniform (CoglContext *ctx,
|
||||
GLint location,
|
||||
const CoglBoxedValue *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;
|
||||
}
|
||||
ctx->driver_vtable->set_uniform (ctx, location, value);
|
||||
}
|
||||
|
@ -46,7 +46,6 @@
|
||||
#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"
|
||||
@ -70,14 +69,12 @@ 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;
|
||||
|
||||
@ -124,9 +121,6 @@ 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;
|
||||
|
||||
@ -315,18 +309,4 @@ 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,40 +45,12 @@
|
||||
#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);
|
||||
@ -470,94 +442,6 @@ _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)
|
||||
{
|
||||
@ -572,24 +456,11 @@ cogl_get_clock_time (CoglContext *context)
|
||||
CoglGraphicsResetStatus
|
||||
cogl_get_graphics_reset_status (CoglContext *context)
|
||||
{
|
||||
if (!context->glGetGraphicsResetStatus)
|
||||
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
|
||||
|
||||
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;
|
||||
}
|
||||
return context->driver_vtable->get_graphics_reset_status (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_context_is_hardware_accelerated (CoglContext *context)
|
||||
{
|
||||
return context->driver_vtable->is_hardware_accelerated (context);
|
||||
}
|
||||
|
@ -357,6 +357,16 @@ 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,6 +35,7 @@
|
||||
#include "cogl-offscreen.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
#include "cogl-sampler-cache-private.h"
|
||||
|
||||
typedef struct _CoglDriverVtable CoglDriverVtable;
|
||||
|
||||
@ -46,6 +47,12 @@ 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
|
||||
@ -262,6 +269,19 @@ 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,10 +43,9 @@ struct _CoglFrameInfo
|
||||
float refresh_rate;
|
||||
|
||||
int64_t global_frame_counter;
|
||||
|
||||
CoglOutput *output;
|
||||
};
|
||||
|
||||
CoglFrameInfo *_cogl_frame_info_new (void);
|
||||
COGL_EXPORT
|
||||
CoglFrameInfo *cogl_frame_info_new (int64_t global_frame_counter);
|
||||
|
||||
#endif /* __COGL_FRAME_INFO_PRIVATE_H */
|
||||
|
@ -39,11 +39,12 @@ COGL_OBJECT_DEFINE (FrameInfo, frame_info);
|
||||
COGL_GTYPE_DEFINE_CLASS (FrameInfo, frame_info);
|
||||
|
||||
CoglFrameInfo *
|
||||
_cogl_frame_info_new (void)
|
||||
cogl_frame_info_new (int64_t global_frame_counter)
|
||||
{
|
||||
CoglFrameInfo *info;
|
||||
|
||||
info = g_slice_new0 (CoglFrameInfo);
|
||||
info->global_frame_counter = global_frame_counter;
|
||||
|
||||
return _cogl_frame_info_object_new (info);
|
||||
}
|
||||
@ -72,12 +73,6 @@ 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,6 +45,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* CoglFrameInfo:
|
||||
*
|
||||
* Frame information.
|
||||
*/
|
||||
typedef struct _CoglFrameInfo CoglFrameInfo;
|
||||
#define COGL_FRAME_INFO(X) ((CoglFrameInfo *)(X))
|
||||
|
||||
@ -126,20 +131,6 @@ 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)
|
||||
*/
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* 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_ */
|
@ -1,189 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
@ -1,572 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cogl-config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <test-fixtures/test-unit.h>
|
||||
|
||||
#include "cogl-gpu-info-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-version.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *renderer_string;
|
||||
const char *version_string;
|
||||
const char *vendor_string;
|
||||
} CoglGpuInfoStrings;
|
||||
|
||||
typedef struct CoglGpuInfoArchitectureDescription
|
||||
{
|
||||
CoglGpuInfoArchitecture architecture;
|
||||
const char *name;
|
||||
CoglGpuInfoArchitectureFlag flags;
|
||||
gboolean (* check_function) (const CoglGpuInfoStrings *strings);
|
||||
|
||||
} CoglGpuInfoArchitectureDescription;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglGpuInfoVendor vendor;
|
||||
const char *name;
|
||||
gboolean (* check_function) (const CoglGpuInfoStrings *strings);
|
||||
const CoglGpuInfoArchitectureDescription *architectures;
|
||||
|
||||
} CoglGpuInfoVendorDescription;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglGpuInfoDriverPackage driver_package;
|
||||
const char *name;
|
||||
gboolean (* check_function) (const CoglGpuInfoStrings *strings,
|
||||
int *version_out);
|
||||
} CoglGpuInfoDriverPackageDescription;
|
||||
|
||||
static gboolean
|
||||
_cogl_gpu_info_parse_version_string (const char *version_string,
|
||||
int n_components,
|
||||
const char **tail,
|
||||
int *version_ret)
|
||||
{
|
||||
int version = 0;
|
||||
uint64_t part;
|
||||
int i;
|
||||
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
errno = 0;
|
||||
part = g_ascii_strtoull (version_string,
|
||||
(char **) &version_string,
|
||||
10);
|
||||
|
||||
if (errno || part > COGL_VERSION_MAX_COMPONENT_VALUE)
|
||||
return FALSE;
|
||||
|
||||
version |= part << ((2 - i) * COGL_VERSION_COMPONENT_BITS);
|
||||
|
||||
if (i + 1 >= n_components)
|
||||
break;
|
||||
|
||||
if (*version_string != '.')
|
||||
return FALSE;
|
||||
|
||||
version_string++;
|
||||
}
|
||||
|
||||
if (version_ret)
|
||||
*version_ret = version;
|
||||
if (tail)
|
||||
*tail = version_string;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
match_phrase (const char *string, const char *phrase)
|
||||
{
|
||||
const char *part = strstr (string, phrase);
|
||||
int len;
|
||||
|
||||
if (part == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* The match must either be at the beginning of the string or
|
||||
preceded by a space. */
|
||||
if (part > string && part[-1] != ' ')
|
||||
return FALSE;
|
||||
|
||||
/* Also match must either be at end of string or followed by a
|
||||
* space. */
|
||||
len = strlen (phrase);
|
||||
if (part[len] != '\0' && part[len] != ' ')
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_intel_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
return match_phrase (strings->renderer_string, "Intel(R)");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_imagination_technologies_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "Imagination Technologies") != 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_arm_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "ARM") != 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_qualcomm_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "Qualcomm") != 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_nvidia_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "NVIDIA") != 0 &&
|
||||
strcmp (strings->vendor_string, "NVIDIA Corporation") != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_ati_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "ATI") != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_mesa_vendor (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strcmp (strings->vendor_string, "Tungsten Graphics, Inc") == 0)
|
||||
return TRUE;
|
||||
else if (strcmp (strings->vendor_string, "VMware, Inc.") == 0)
|
||||
return TRUE;
|
||||
else if (strcmp (strings->vendor_string, "Mesa Project") == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_true (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
/* This is a last resort so it always matches */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_sandybridge_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
return match_phrase (strings->renderer_string, "Sandybridge");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_llvmpipe_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
return match_phrase (strings->renderer_string, "llvmpipe");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_softpipe_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
return match_phrase (strings->renderer_string, "softpipe");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_swrast_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
return match_phrase (strings->renderer_string, "software rasterizer") ||
|
||||
match_phrase (strings->renderer_string, "Software Rasterizer");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_sgx_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strncmp (strings->renderer_string, "PowerVR SGX", 12) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_mali_architecture (const CoglGpuInfoStrings *strings)
|
||||
{
|
||||
if (strncmp (strings->renderer_string, "Mali-", 5) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const CoglGpuInfoArchitectureDescription
|
||||
intel_architectures[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE,
|
||||
"Sandybridge",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
|
||||
check_sandybridge_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
|
||||
"Unknown",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
|
||||
check_true
|
||||
}
|
||||
};
|
||||
|
||||
static const CoglGpuInfoArchitectureDescription
|
||||
powervr_architectures[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_SGX,
|
||||
"SGX",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_DEFERRED,
|
||||
check_sgx_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
|
||||
"Unknown",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED,
|
||||
check_true
|
||||
}
|
||||
};
|
||||
|
||||
static const CoglGpuInfoArchitectureDescription
|
||||
arm_architectures[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_MALI,
|
||||
"Mali",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
|
||||
check_mali_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
|
||||
"Unknown",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_TILED |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
|
||||
check_true
|
||||
}
|
||||
};
|
||||
|
||||
static const CoglGpuInfoArchitectureDescription
|
||||
mesa_architectures[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE,
|
||||
"LLVM Pipe",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
|
||||
check_llvmpipe_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE,
|
||||
"Softpipe",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
|
||||
check_softpipe_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_SWRAST,
|
||||
"SWRast",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_SOFTWARE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_SOFTWARE,
|
||||
check_swrast_architecture
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
|
||||
"Unknown",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_FRAGMENT_IMMEDIATE_MODE,
|
||||
check_true
|
||||
}
|
||||
};
|
||||
|
||||
static const CoglGpuInfoArchitectureDescription
|
||||
unknown_architectures[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_ARCHITECTURE_UNKNOWN,
|
||||
"Unknown",
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE |
|
||||
COGL_GPU_INFO_ARCHITECTURE_FLAG_VERTEX_IMMEDIATE_MODE,
|
||||
check_true
|
||||
}
|
||||
};
|
||||
|
||||
static const CoglGpuInfoVendorDescription
|
||||
_cogl_gpu_info_vendors[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_INTEL,
|
||||
"Intel",
|
||||
check_intel_vendor,
|
||||
intel_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_IMAGINATION_TECHNOLOGIES,
|
||||
"Imagination Technologies",
|
||||
check_imagination_technologies_vendor,
|
||||
powervr_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_ARM,
|
||||
"ARM",
|
||||
check_arm_vendor,
|
||||
arm_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_QUALCOMM,
|
||||
"Qualcomm",
|
||||
check_qualcomm_vendor,
|
||||
unknown_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_NVIDIA,
|
||||
"Nvidia",
|
||||
check_nvidia_vendor,
|
||||
unknown_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_ATI,
|
||||
"ATI",
|
||||
check_ati_vendor,
|
||||
unknown_architectures
|
||||
},
|
||||
/* Must be last */
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_MESA,
|
||||
"Mesa",
|
||||
check_mesa_vendor,
|
||||
mesa_architectures
|
||||
},
|
||||
{
|
||||
COGL_GPU_INFO_VENDOR_UNKNOWN,
|
||||
"Unknown",
|
||||
check_true,
|
||||
unknown_architectures
|
||||
}
|
||||
};
|
||||
|
||||
static gboolean
|
||||
check_mesa_driver_package (const CoglGpuInfoStrings *strings,
|
||||
int *version_ret)
|
||||
{
|
||||
uint64_t micro_part;
|
||||
const char *v;
|
||||
|
||||
/* The version string should always begin a two-part GL version
|
||||
number */
|
||||
if (!_cogl_gpu_info_parse_version_string (strings->version_string,
|
||||
2, /* n_components */
|
||||
&v, /* tail */
|
||||
NULL /* version_ret */))
|
||||
return FALSE;
|
||||
|
||||
/* In mesa this will be followed optionally by "(Core Profile)" and
|
||||
* then "Mesa" */
|
||||
v = strstr (v, " Mesa ");
|
||||
if (!v)
|
||||
return FALSE;
|
||||
|
||||
v += 6;
|
||||
|
||||
/* Next there will be a version string that is at least two
|
||||
components. On a git devel build the version will be something
|
||||
like "-devel<git hash>" instead */
|
||||
if (!_cogl_gpu_info_parse_version_string (v,
|
||||
2, /* n_components */
|
||||
&v, /* tail */
|
||||
version_ret))
|
||||
return FALSE;
|
||||
|
||||
/* If it is a development build then we'll just leave the micro
|
||||
number as 0 */
|
||||
if (g_str_has_prefix (v, "-devel"))
|
||||
return TRUE;
|
||||
|
||||
/* Otherwise there should be a micro version number */
|
||||
if (*v != '.')
|
||||
return FALSE;
|
||||
|
||||
errno = 0;
|
||||
micro_part = g_ascii_strtoull (v + 1, NULL /* endptr */, 10 /* base */);
|
||||
if (errno || micro_part > COGL_VERSION_MAX_COMPONENT_VALUE)
|
||||
return FALSE;
|
||||
|
||||
*version_ret = COGL_VERSION_ENCODE (COGL_VERSION_GET_MAJOR (*version_ret),
|
||||
COGL_VERSION_GET_MINOR (*version_ret),
|
||||
micro_part);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UNIT_TEST (check_mesa_driver_package_parser,
|
||||
0, /* no requirements */
|
||||
0 /* no failure cases */)
|
||||
{
|
||||
/* renderer_string, version_string, vendor_string;*/
|
||||
const CoglGpuInfoStrings test_strings[2] = {
|
||||
{ NULL, "3.1 Mesa 9.2-devel15436ad", NULL },
|
||||
{ NULL, "3.1 (Core Profile) Mesa 9.2.0-devel (git-15436ad)", NULL }
|
||||
};
|
||||
int i;
|
||||
int version;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test_strings); i++)
|
||||
{
|
||||
g_assert (check_mesa_driver_package (&test_strings[i], &version));
|
||||
g_assert_cmpint (version, ==, COGL_VERSION_ENCODE (9, 2, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_unknown_driver_package (const CoglGpuInfoStrings *strings,
|
||||
int *version_out)
|
||||
{
|
||||
*version_out = 0;
|
||||
|
||||
/* This is a last resort so it always matches */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const CoglGpuInfoDriverPackageDescription
|
||||
_cogl_gpu_info_driver_packages[] =
|
||||
{
|
||||
{
|
||||
COGL_GPU_INFO_DRIVER_PACKAGE_MESA,
|
||||
"Mesa",
|
||||
check_mesa_driver_package
|
||||
},
|
||||
/* Must be last */
|
||||
{
|
||||
COGL_GPU_INFO_DRIVER_PACKAGE_UNKNOWN,
|
||||
"Unknown",
|
||||
check_unknown_driver_package
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
_cogl_gpu_info_init (CoglContext *ctx,
|
||||
CoglGpuInfo *gpu)
|
||||
{
|
||||
CoglGpuInfoStrings strings;
|
||||
int i;
|
||||
|
||||
strings.renderer_string = (const char *) ctx->glGetString (GL_RENDERER);
|
||||
strings.version_string = _cogl_context_get_gl_version (ctx);
|
||||
strings.vendor_string = (const char *) ctx->glGetString (GL_VENDOR);
|
||||
|
||||
/* Determine the driver package */
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
const CoglGpuInfoDriverPackageDescription *description =
|
||||
_cogl_gpu_info_driver_packages + i;
|
||||
|
||||
if (description->check_function (&strings, &gpu->driver_package_version))
|
||||
{
|
||||
gpu->driver_package = description->driver_package;
|
||||
gpu->driver_package_name = description->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the GPU vendor */
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
const CoglGpuInfoVendorDescription *description =
|
||||
_cogl_gpu_info_vendors + i;
|
||||
|
||||
if (description->check_function (&strings))
|
||||
{
|
||||
int j;
|
||||
|
||||
gpu->vendor = description->vendor;
|
||||
gpu->vendor_name = description->name;
|
||||
|
||||
for (j = 0; ; j++)
|
||||
{
|
||||
const CoglGpuInfoArchitectureDescription *architecture =
|
||||
description->architectures + j;
|
||||
|
||||
if (architecture->check_function (&strings))
|
||||
{
|
||||
gpu->architecture = architecture->architecture;
|
||||
gpu->architecture_name = architecture->name;
|
||||
gpu->architecture_flags = architecture->flags;
|
||||
goto probed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
probed:
|
||||
|
||||
COGL_NOTE (WINSYS, "Driver package = %s, vendor = %s, architecture = %s\n",
|
||||
gpu->driver_package_name,
|
||||
gpu->vendor_name,
|
||||
gpu->architecture_name);
|
||||
|
||||
/* Determine the driver bugs */
|
||||
gpu->driver_bugs = 0;
|
||||
}
|
@ -41,7 +41,6 @@
|
||||
#include "cogl-matrix-private.h"
|
||||
#include "cogl-magazine-private.h"
|
||||
#include "cogl-gtype-private.h"
|
||||
#include "driver/gl/cogl-util-gl-private.h"
|
||||
|
||||
static void _cogl_matrix_stack_free (CoglMatrixStack *stack);
|
||||
|
||||
|
@ -293,15 +293,14 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
|
||||
void
|
||||
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
@ -310,7 +309,8 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles, n_rectangles);
|
||||
rectangles, n_rectangles,
|
||||
info);
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH |
|
||||
@ -334,23 +334,23 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0);
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0, info);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
@ -365,7 +365,8 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
|
||||
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
n_rectangles,
|
||||
info);
|
||||
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
@ -406,22 +407,21 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout)
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT));
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_direct_scanout (onscreen, scanout);
|
||||
winsys->onscreen_direct_scanout (onscreen, scanout, info);
|
||||
|
||||
onscreen->frame_counter++;
|
||||
}
|
||||
|
@ -178,7 +178,8 @@ cogl_onscreen_hide (CoglOnscreen *onscreen);
|
||||
* Stability: unstable
|
||||
*/
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen);
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
|
||||
CoglFrameInfo *frame_info);
|
||||
|
||||
|
||||
/**
|
||||
@ -284,14 +285,16 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* cogl_onscreen_direct_scanout: (skip)
|
||||
*/
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout);
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* cogl_onscreen_swap_region:
|
||||
@ -316,7 +319,8 @@ cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* CoglFrameEvent:
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "cogl-node-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "driver/gl/cogl-pipeline-opengl-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -342,8 +341,6 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
|
||||
CoglPipelineLayer *layer,
|
||||
CoglPipelineLayerState change)
|
||||
{
|
||||
CoglTextureUnit *unit;
|
||||
|
||||
/* Identify the case where the layer is new with no owner or
|
||||
* dependants and so we don't need to do anything. */
|
||||
if (_cogl_list_empty (&COGL_NODE (layer)->children) &&
|
||||
@ -403,15 +400,6 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
|
||||
progend->layer_pre_change_notify (required_owner, layer, change);
|
||||
}
|
||||
|
||||
/* If the layer being changed is the same as the last layer we
|
||||
* flushed to the corresponding texture unit then we keep a track of
|
||||
* the changes so we can try to minimize redundant OpenGL calls if
|
||||
* the same layer is flushed again.
|
||||
*/
|
||||
unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
|
||||
if (unit->layer == layer)
|
||||
unit->layer_changes_since_flush |= change;
|
||||
|
||||
init_layer_state:
|
||||
|
||||
if (required_owner)
|
||||
|
@ -51,22 +51,6 @@
|
||||
#include "cogl-pixel-buffer.h"
|
||||
#include "cogl-gtype-private.h"
|
||||
|
||||
/*
|
||||
* GL/GLES compatibility defines for the buffer API:
|
||||
*/
|
||||
|
||||
#if defined (HAVE_COGL_GL)
|
||||
|
||||
#ifndef GL_PIXEL_UNPACK_BUFFER
|
||||
#define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB
|
||||
#endif
|
||||
|
||||
#ifndef GL_PIXEL_PACK_BUFFER
|
||||
#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
_cogl_pixel_buffer_free (CoglPixelBuffer *buffer);
|
||||
|
||||
|
@ -34,11 +34,6 @@
|
||||
|
||||
#include "cogl-sampler-cache-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "driver/gl/cogl-util-gl-private.h"
|
||||
|
||||
#ifndef GL_TEXTURE_WRAP_R
|
||||
#define GL_TEXTURE_WRAP_R 0x8072
|
||||
#endif
|
||||
|
||||
struct _CoglSamplerCache
|
||||
{
|
||||
@ -54,10 +49,6 @@ struct _CoglSamplerCache
|
||||
GL state. */
|
||||
GHashTable *hash_table_cogl;
|
||||
GHashTable *hash_table_gl;
|
||||
|
||||
/* This is used for generated fake unique sampler object numbers
|
||||
when the sampler object extension is not supported */
|
||||
GLuint next_fake_sampler_object_number;
|
||||
};
|
||||
|
||||
static CoglSamplerCacheWrapMode
|
||||
@ -176,22 +167,10 @@ _cogl_sampler_cache_new (CoglContext *context)
|
||||
sampler_state_equal_gl);
|
||||
cache->hash_table_cogl = g_hash_table_new (hash_sampler_state_cogl,
|
||||
sampler_state_equal_cogl);
|
||||
cache->next_fake_sampler_object_number = 1;
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void
|
||||
set_wrap_mode (CoglContext *context,
|
||||
GLuint sampler_object,
|
||||
GLenum param,
|
||||
CoglSamplerCacheWrapMode wrap_mode)
|
||||
{
|
||||
GE( context, glSamplerParameteri (sampler_object,
|
||||
param,
|
||||
wrap_mode) );
|
||||
}
|
||||
|
||||
static CoglSamplerCacheEntry *
|
||||
_cogl_sampler_cache_get_entry_gl (CoglSamplerCache *cache,
|
||||
const CoglSamplerCacheEntry *key)
|
||||
@ -202,39 +181,9 @@ _cogl_sampler_cache_get_entry_gl (CoglSamplerCache *cache,
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
CoglContext *context = cache->context;
|
||||
|
||||
entry = g_slice_dup (CoglSamplerCacheEntry, key);
|
||||
|
||||
if (_cogl_has_private_feature (context,
|
||||
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
|
||||
{
|
||||
GE( context, glGenSamplers (1, &entry->sampler_object) );
|
||||
|
||||
GE( context, glSamplerParameteri (entry->sampler_object,
|
||||
GL_TEXTURE_MIN_FILTER,
|
||||
entry->min_filter) );
|
||||
GE( context, glSamplerParameteri (entry->sampler_object,
|
||||
GL_TEXTURE_MAG_FILTER,
|
||||
entry->mag_filter) );
|
||||
|
||||
set_wrap_mode (context,
|
||||
entry->sampler_object,
|
||||
GL_TEXTURE_WRAP_S,
|
||||
entry->wrap_mode_s);
|
||||
set_wrap_mode (context,
|
||||
entry->sampler_object,
|
||||
GL_TEXTURE_WRAP_T,
|
||||
entry->wrap_mode_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If sampler objects aren't supported then we'll invent a
|
||||
unique number so that pipelines can still compare the
|
||||
unique state just by comparing the sampler object
|
||||
numbers */
|
||||
entry->sampler_object = cache->next_fake_sampler_object_number++;
|
||||
}
|
||||
cache->context->driver_vtable->sampler_init (cache->context, entry);
|
||||
|
||||
g_hash_table_insert (cache->hash_table_gl, entry, entry);
|
||||
}
|
||||
@ -320,9 +269,7 @@ hash_table_free_gl_cb (void *key,
|
||||
CoglContext *context = user_data;
|
||||
CoglSamplerCacheEntry *entry = value;
|
||||
|
||||
if (_cogl_has_private_feature (context,
|
||||
COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
|
||||
GE( context, glDeleteSamplers (1, &entry->sampler_object) );
|
||||
context->driver_vtable->sampler_free (context, entry);
|
||||
|
||||
g_slice_free (CoglSamplerCacheEntry, entry);
|
||||
}
|
||||
|
@ -402,6 +402,11 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
|
||||
{
|
||||
CoglContext *ctx = tex->context;
|
||||
|
||||
/* Since we are about to ask the GPU to generate mipmaps of tex, we
|
||||
* better make sure tex is up-to-date.
|
||||
*/
|
||||
_cogl_texture_flush_journal_rendering (tex);
|
||||
|
||||
ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d);
|
||||
|
||||
tex_2d->mipmaps_dirty = FALSE;
|
||||
|
@ -62,11 +62,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
/* This isn't defined in the GLES headers */
|
||||
#ifndef GL_RED
|
||||
#define GL_RED 0x1903
|
||||
#endif
|
||||
|
||||
COGL_GTYPE_DEFINE_INTERFACE (Texture, texture);
|
||||
|
||||
uint32_t
|
||||
@ -786,8 +781,6 @@ cogl_texture_get_data (CoglTexture *texture,
|
||||
if (texture_format == COGL_PIXEL_FORMAT_A_8)
|
||||
{
|
||||
closest_format = COGL_PIXEL_FORMAT_A_8;
|
||||
closest_gl_format = GL_RED;
|
||||
closest_gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (format == COGL_PIXEL_FORMAT_A_8)
|
||||
{
|
||||
@ -798,8 +791,6 @@ cogl_texture_get_data (CoglTexture *texture,
|
||||
* pre-multiplied here because we're only going to look at
|
||||
* the alpha component */
|
||||
closest_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
closest_gl_format = GL_RGBA;
|
||||
closest_gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "cogl-config.h"
|
||||
|
||||
#include "cogl-util.h"
|
||||
#include "driver/gl/cogl-util-gl-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-object-private.h"
|
||||
|
||||
|
@ -47,16 +47,4 @@ struct _CoglShader
|
||||
char *source;
|
||||
};
|
||||
|
||||
void
|
||||
_cogl_shader_compile_real (CoglHandle handle,
|
||||
CoglPipeline *pipeline);
|
||||
|
||||
void
|
||||
_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
|
||||
GLenum shader_gl_type,
|
||||
int n_tex_coord_attribs,
|
||||
GLsizei count_in,
|
||||
const char **strings_in,
|
||||
const GLint *lengths_in);
|
||||
|
||||
#endif /* __COGL_SHADER_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user