We need to make sure that redraws queued for actors on a stage are for
actors actually in the stage. So in clutter_actor_unparent() descend
through the children and remove redraws. Just removing the actor itself
isn't good enough since an entire hierarchy can be removed from the
stage without breaking it up into individual actors.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2359
This is based on an original patch from Owen Taylor who debugged the
root cause of this bug; thanks.
Instead of delegating the check for the ActorMeta:enabled property to
the sub-classes of ClutterActorMeta, ClutterActor can do the check prior
to using the ClutterActorMeta instances.
In all the changes made recently to how we handle redraws and adding
support for paint-volumes we stopped looking at explicit clip regions
passed to _clutter_actor_queue_redraw_with_clip.
In _clutter_actor_finish_queue_redraw we had started always trying to
clip the redraw to the paint-volume of the actor, but forgot to consider
that the user may have already determined the clip region for us!
Now we first check if the given clip != NUll and if so we don't need to
calculate the paint-volume of the actor.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2349
Since re-working how redraws are queued it is no longer necessary to
dirty the pick buffer in _clutter_actor_real_queue_redraw since this
should now reliably be handled in _clutter_stage_queue_actor_redraw.
This adds two internal functions relating to explicit traversal of the
scenegraph:
_clutter_actor_foreach_child
_clutter_actor_traverse
_clutter_actor_foreach_child just iterates the immediate children of an
actor, and with a new ClutterForeachCallback type it allows the
callbacks to break iteration early.
_clutter_actor_traverse traverses the given actor and all of its
decendants. Again traversal can be stopped early if a callback returns
FALSE.
The first intended use for _clutter_actor_traverse is to maintain a
cache pointer to the stage for all actors. In this case we will need to
update the pointer for all descendants of an actor when an actor is
reparented in any way.
This adds a private getter to query the number of children an actor has.
One use planned for this API is to avoid calling get_paint_volume on
such actors. (It's not clear what the best semantics for
get_paint_volume are for actors with children, so we are considering
leaving the semantics undefined for the initial clutter 1.4 release)
We now explicitly track the list of children each actor has in a private
GList. This gives us a reliable way to know how many children an actor
has - even for composite actors that don't implement the container
interface. This also will allow us to directly traverse the scenegraph
in a more generalized fashion. Previously the scenegraph was
more-or-less represented implicitly according the implementation of
paint methods.
When using the CLUTTER_PAINT=paint-volumes debug option we try and show
when a paint volume couldn't be determined by drawing a blue outline of
the allocation instead. There was a typo though and instead we were
drawing an outline the size of the stage instead of for the given actor.
This fixes that and removes a FIXME comment relating to the blue outline
that is now implemented.
This reverts commit ca44c6a7d8abe9f2c548bee817559ea8adaa7a80.
In reality there are probably lots of actors that depend on the exact
semantics as they are documented so this change isn't really acceptable.
For example when the font changes in ClutterText we only queue a
relayout, and since it's possible that the font will have the same size
and the actor won't get a new allocation it wouldn't otherwise queue a
redraw.
Since queue_redraw requests now get deferred until just before a paint
run it is actually no longer a problem to queue the redraw here.
Instead of immediately, recursively emitting the "queue-redraw" signal
when clutter_actor_queue_redraw is called we now defer this process
until all stage updates are complete. This allows us to aggregate
repeated _queue_redraw requests for the same actor avoiding redundant
paint volume transformations. By deferring we also increase the
likelihood that the actor will have a valid paint volume since it will
have an up to date allocation; this in turn means we will more often be
able to automatically queue clipped redraws which can have a big impact
on performance.
Here's an outline of the actor queue redraw mechanism:
The process starts in clutter_actor_queue_redraw or
_clutter_actor_queue_redraw_with_clip.
These functions queue an entry in a list associated with the stage which
is a list of actors that queued a redraw while updating the timelines,
performing layouting and processing other mainloop sources before the
next paint starts.
We aim to minimize the processing done at this point because there is a
good chance other events will happen while updating the scenegraph that
would invalidate any expensive work we might otherwise try to do here.
For example we don't try and resolve the screen space bounding box of an
actor at this stage so as to minimize how much of the screen redraw
because it's possible something else will happen which will force a full
redraw anyway.
When all updates are complete and we come to paint the stage (see
_clutter_stage_do_update) then we iterate this list and actually emit
the "queue-redraw" signals for each of the listed actors which will
bubble up to the stage for each actor and at that point we will
transform the actors paint volume into screen coordinates to determine
the clip region for what needs to be redrawn in the next paint.
Note: actors are allowed to queue a redraw in reseponse to a
queue-redraw signal so we repeat the processing of the list until it
remains empty. An example of when this happens is for Clone actors or
clutter_texture_new_from_actor actors which need to queue a redraw if
their source queues a redraw.
This makes clutter_actor_queue_redraw simply bail out early if the actor
isn't a descendant of a ClutterStage since the request isn't meaningful
and it avoids a crash when trying to queue a clipped redraw against the
stage to clear the actors old location.
This splits out all the clutter_paint_volume code from clutter-actor.c
into clutter-paint-volume.c. Since clutter-actor.c and
clutter-paint-volume.c both needed the functionality of
_fully_transform_vertices, this function has now been moved to
clutter-utils.c as _clutter_util_fully_transform_vertices.
There are too many examples where the default assumption that an actor
paints inside its allocation isn't true, so we now return FALSE in the
base implementation instead. This means that by default we are saying
"we don't know the paint volume of the actor", so developers need to
implement the get_paint_volume virtual to take advantage of culling and
clipped redraws with their actors.
This patch provides very conservative get_paint_volume implementations
for ClutterTexture, ClutterCairoTexture, ClutterRectangle and
ClutterText which all explicitly check the actor's object type to avoid
making any assumptions about subclasses.
We were always explicitly checking priv->needs_allocation in
_clutter_actor_queue_redraw_with_clip, but we only need to do that if
the CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION flag is used.
This initializes priv->last_paint_box with a degenerate box, so a newly
allocated actor added to the scenegraph and made visible only needs to
trigger a redraw of its initial position. If we don't have a valid
last_paint_box though we would instead trigger a full stage redraw.
To make comparing the performance with culling/clipped redraws
enabled/disabled fairer we now avoid querying the paint box when they
are disabled, so that results should reflect how the cost of
transforming paint volumes into screen space etc gets offset against the
benefit of culling.
We have bent the originally documented semantics a bit so now where we
say "Queueing a new layout automatically queues a redraw as well" it
might be clearer to say "Queuing a new layout implicitly queues a redraw
as well if anything in the layout changes".
This should be close enough to the original semantics to not cause any
problems.
Without this change then we we fail to take advantage of clipped redraws
in a lot of cases because queuing a redraw with priv->needs_allocation
== TRUE will automatically be promoted to a full stage redraw since it's
not possible to determine a valid paint-volume.
Also queuing a redraw here will end up registering a redundant clipped
redraw for the current location, doing quite a lot of redundant
transforms, and then later when re-allocated during layouting another
queue redraw would happen with the correct paint-volume.
This uses actor paint volumes to perform culling during
clutter_actor_paint.
When performing a clipped redraw (because only a few localized actors
changed) then as we traverse the scenegraph painting the actors we can
now ignore actors that don't intersect the clip region. Early testing
shows this can have a big performance benefit; e.g. 100% fps improvement
for test-state with culling enabled and we hope that there are even much
more compelling examples than that in the real world,
Most Clutter applications are 2Dish interfaces and have quite a lot of
actors that get continuously painted when anything is animated. The
dynamic actors are often localized to an area of user focus though so
with culling we can completely avoid painting any of the static actors
outside the current clip region.
Obviously the cost of culling has to be offset against the cost of
painting to determine if it's a win, but our (limited) testing suggests
it should be a win for most applications.
Note: we hope we will be able to also bring another performance bump
from culling with another iteration - hopefully in the 1.6 cycle - to
avoid doing the culling in screen space and instead do it in the stage's
model space. This will hopefully let us minimize the cost of
transforming the actor volumes for culling.
This makes clutter_actor_queue_redraw transparently use an actor's paint
volume to queue a clipped redraw.
We save the actors paint box each time it is painted so that when
clutter_actor_queue_redraw is called we can determine the old and new
location of the actor so we know the full bounds of what must be redrawn
to clear its old view and show the new.
This makes _clutter_actor_transform_and_project_box a static function
and removes the prototype from clutter-private.h since it is no longer
used outside clutter-actor.c
The base implementation for the actor queue_relayout method was queuing
an implicit redraw, but there shouldn't be anything implied from the
mere process of queuing a redraw that should force us to queue a redraw.
If actors are moved as a part of relayouting later then they will queue
a redraw. Also clutter_actor_queue_relayout() still also explicitly
queues a redraw so I think this may have been doubly redundant.
If clutter_actor_allocate finds it necessary to update an actors
allocation then it now also queue a redraw of that actor. Currently we
queue redraws for actors very early on when queuing a relayout instead
of waiting to determine the final outcome of relayouting to determine if
a redraw is really required. With this in place we can move away from
preemptive queuing of redraws.
clutter_actor_queue_relayout currently queues a relayout and a redraw,
but the plan is to change it to only queue a relayout and honour the
documentation by assuming that the process of relayouting will
result queuing redraws for any actors whos allocation changes.
This doesn't make that change it just adds an internal
_clutter_actor_queue_only_relayout function which
clutter_actor_queue_relayout now uses as well as calling
clutter_actor_queue_redraw.
There is an internal _clutter_actor_queue_redraw_with_clip API that gets
used for texture-from-pixmap to minimize what we redraw in response to
Damage events. It was previously working in terms of a ClutterActorBox
but it has now been changed so an actor can queue a redraw of volume
instead.
The plan is that clutter_actor_queue_redraw will start to transparently
use _clutter_actor_queue_redraw_with_clip when it can determine a paint
volume for the actor.
This adds a debug option to visualize the paint volumes of all actors.
When CLUTTER_PAINT=paint-volumes is exported in the environment before
running a Clutter application then all actors will have their bounding
volume drawn in green with a label corresponding to the actors type.
This is a fairly extensive second pass at exposing paint volumes for
actors.
The API has changed to allow clutter_actor_get_paint_volume to fail
since there are times - such as when an actor isn't a descendent of the
stage - when the volume can't be determined. Another example is when
something has connected to the "paint" signal of the actor and we simply
have no way of knowing what might be drawn in that handler.
The API has also be changed to return a const ClutterPaintVolume pointer
(transfer none) so we can avoid having to dynamically allocate the
volumes in the most common/performance critical code paths. Profiling was
showing the slice allocation of volumes taking about 1% of an apps time,
for some fairly basic tests. Most volumes can now simply be allocated on
the stack; for clutter_actor_get_paint_volume we return a pointer to
&priv->paint_volume and if we need a more dynamic allocation there is
now a _clutter_stage_paint_volume_stack_allocate() mechanism which lets
us allocate data which expires at the start of the next frame.
The API has been extended to make it easier to implement
get_paint_volume for containers by using
clutter_actor_get_transformed_paint_volume and
clutter_paint_volume_union. The first allows you to query the paint
volume of a child but transformed into parent actor coordinates. The
second lets you combine volumes together so you can union all the
volumes for a container's children and report that as the container's
own volume.
The representation of paint volumes has been updated to consider that
2D actors are the most common.
The effect apis, clutter-texture and clutter-group have been update
accordingly.
An Effect implementation might override the paint volume of the actor to
which it is applied to. The get_paint_volume() virtual function should
be added to the Effect class vtable so that any effect can get the
current paint volume and update it.
The clutter_actor_get_paint_volume() function becomes context aware, and
does the right thing if called from within a ClutterEffect pre_paint()
or post_paint() implementation, by allowing all effects in the chain up
to the caller to modify the paint volume.
An actor has an implicit "paint volume", that is the volume in 3D space
occupied when painting itself.
The paint volume is defined as a cuboid with the origin placed at the
top-left corner of the actor; the size of the cuboid is given by three
vectors: width, height and depth.
ClutterActor provides API to convert the paint volume into a 2D box in
screen coordinates, to compute the on-screen area that an actor will
occupy when painted.
Actors can override the default implementation of the get_paint_volume()
virtual function to provide a different volume.
This reorganizes the loop for clutter_actor_contains so that it is a
for loop rather than a while loop. Although this is mostly just
nitpicking, I think this change could make the loop slightly faster if
not optimized because it doesn't perform the self == descendant check
twice and it is clearer.
The documentation for clutter_actor_contains didn't specify what
happens when self==descendant. A strict reading of it might lead you
to think that it would return FALSE because in that case the
descendant isn't an immediate child or a deeper descendant. The code
actually would return TRUE. I think this is more useful so this patch
fixes the docs rather than the code.
This adds a check in clutter_actor_real_queue_redraw after calling
_clutter_actor_get_stage_internal to check in case the actor doesn't yet
have an associated stage so we can avoid passing a NULL stage pointer to
_clutter_stage_set_pick_buffer_valid which could cause a crash.
We have an optimization to track when there are multiple picks per
frame so we can do a full render of the pick buffer to reduce the
number of pick renders for a static scene.
There was a problem though in that we were tracking this information in
the ClutterMainContext, but conceptually this doesn't really make sense
because the pick buffer is associated with a stage framebuffer and there
can be multiple stages for one context.
This patch moves the state tracking to ClutterStage.
This reverts commit d7e86e2696.
This was a half baked patch that was pushed a bit early since it broke
test-texture-pick-with-alpha + the commit message refers to a change on
the wip/paint-box branch that hasn't happened yet.
We have an optimization to track when there are multiple picks per
frames so we can do a full render of the pick buffer to reduce the
number of pick renders for a static scene.
There were two problems with how we were tracking this state though.
Firstly we were tracking this information in the ClutterMainContext, but
conceptually this doesn't really make sense because the pick buffer is
associated with a stage framebuffer and there can be multiple stages for
one context. Secondly - since the change to how redraws are queued - we
weren't marking the pick buffer as invalid when a queuing a redraw, we
were only marking the buffer invalid when signaling/finishing the
queue-redraw process, which is now deferred until just before a paint.
This meant using clutter_stage_get_actor_at_pos after a scenegraph
change could give a wrong result if it just read from an existing (but
technically invalid) pick buffer.
This patch moves the state tracking to ClutterStage, and ensures the
buffer is invalidated in _clutter_stage_queue_actor_redraw.
http://bugzilla.clutter-project.org/show_bug.cgi?id=2283
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
The Constraint should plug directly into the allocation mechanism, and
modify the allocation of the actor to which they are applied to. This is
similar to the mechanism used by the Effect class to modify the paint
sequence of an actor.
This adds a verbose warning that will be displayed if
clutter_actor_allocate is passed an actor that isn't a descendent of a
ClutterStage. Layouting should always bubble up from a stage so this
condition is likely to indicate a buggy container that allocating a
child that it has already unparented.
When building actor relative transforms, instead of using the matrix
stack to combine transformations and making assumptions about what is
currently on the stack we now just explicitly initialize an identity
matrix and apply transforms to that.
This removes the full_vertex_t typedef for internal transformation code
and we just use ClutterVertex.
ClutterStage now implements apply_transform like any other actor now
and the code we had in _cogl_setup_viewport has been moved to the
stage's apply_transform instead.
ClutterStage now tracks an explicit projection matrix and viewport
geometry. The projection matrix is derived from the perspective whenever
that changes, and the viewport is updated when the stage gets a new
allocation. The SYNC_MATRICES mechanism has been removed in favour of
_clutter_stage_dirty_viewport/projection() APIs that get used when
switching between multiple stages to ensure cogl has the latest
information about the onscreen framebuffer.
This adds _clutter_actor_get_stage_internal to clutter-private.h since
we plan to use it in clutter-offscreen-effect when preparing to
redirect an actor offscreen.
Comprehensively add (out) annotations to functions parameters
returning int/float/double.
Not handled here: structure out returns like ClutterColor or
ClutterPerspective or GValue that should get (out caller-allocates).
Not handled here: Cogl
http://bugzilla.clutter-project.org/show_bug.cgi?id=2302
This clarifies the documentation for clutter_actor_queue_redraw to
explain that custom actors should call this whenever some private state
changes that affects painting *or* picking.
The idea is that if we see multiple picks per frame then that implies
the visible scene has become static. In this case we can promote the
next pick render to be unclipped so we have valid pick values for the
entire stage. Now we can continue to read from this cached buffer until
the stage contents do visibly change.
Thanks to Luca Bruno on #clutter for this idea!
* wip/table-layout:
Add ClutterTableLayout, a layout showing children in rows and columns
box-layout: Use allocate_align_fill()
bin-layout: Migrate to allocate_align_fill()
actor: Add allocate_align_fill()
test-flow-layout: Use BindConstraints
Layout managers are using the same code to allocate a child while taking
into consideration:
• horizontal and vertical alignment
• horizontal and vertical fill
• the preferred minimum and natural size, depending
on the :request-mode property
• the text direction for the horizontal alignment
• an offset given by the fixed position properties
Given the amount of code involved, and the amount of details that can go
horribly wrong while copy and pasting such code in various classes - let
alone various projects - Clutter should provide an allocate() variant
that does the right thing in the right way. This way, we have a single
point of failure.
This adds a wrapper macro to clutter-private that will use
g_object_notify_by_pspec if it's compiled against a version of GLib
that is sufficiently new. Otherwise it will notify by the property
name as before by extracting the name from the pspec. The objects can
then store a static array of GParamSpecs and notify using those as
suggested in the documentation for g_object_notify_by_pspec.
Note that the name of the variable used for storing the array of
GParamSpecs is obj_props instead of properties as used in the
documentation because some places in Clutter uses 'properties' as the
name of a local variable.
Mose of the classes in Clutter have been converted using the script in
the bug report. Some classes have not been modified even though the
script picked them up as described here:
json-generator:
We probably don't want to modify the internal copy of JSON
behaviour-depth:
rectangle:
score:
stage-manager:
These aren't using the separate GParamSpec* variable style.
blur-effect:
win32/device-manager:
Don't actually define any properties even though it has the enum.
box-layout:
flow-layout:
Have some per-child properties that don't work automatically with
the script.
clutter-model:
The script gets confused with ClutterModelIter
stage:
Script gets confused because PROP_USER_RESIZE doesn't match
"user-resizable"
test-layout:
Don't really want to modify the tests
http://bugzilla.clutter-project.org/show_bug.cgi?id=2150
The Animatable interface was created specifically for the Animation
class. It turns out that it might be fairly useful to others - such as
ClutterAnimator and ClutterState.
The newly-added API in this cycle for querying and accessing custom
properties should not require that we pass a ClutterAnimation to the
implementations: the Animatable itself should be enough.
This is necessary to allow language bindings to wrap
clutter_actor_animate() correctly and do type validation and
demarshalling between native values and GValues; an Animation instance
is not available until the animate() call returns, and validation must
be performed before that happens.
There is nothing we can do about the animate_property() virtual
function - but in that case we might want to be able to access the
animation from an Animatable implementation to get the Interval for
the property, just like ClutterActor does in order to animate
ClutterActorMeta objects.
It's possible - though not recommended - that user code causes the
destruction of an actor in one of the notification handlers for
flag-based properties. We should protect the multiple notification
emission with g_object_ref/unref.
Up until now, the "behaviours" member of an actor definition was parsed
by the ClutterScript parser itself - even though it's not strictly
necessary.
In an effort to minimize the ad hoc code in the Script parser, we should
let ClutterActor handle all the special cases that involve
actor-specific members.
The scanner has some issues when parsing valid gtk-doc annotations; we
should make its (and, in return, ours) life easier.
We still get warnings for code declared in <programlisting> sections,
unfortunately.
ClutterActor should allow attaching actions, constraints and effects
just like it allows behaviours, e.g.:
{
...
"constraints" : [
{
"type" : "ClutterAlignConstraint",
"source" : "stage",
"align-axis" : "x-axis",
"factor" : 0.5
},
{
"type" : "ClutterAlignConstraint",
"source" : "stage",
"align-axis" : "y-axis",
"factor" : 0.5
}
],
...
}
or:
{
...
"actions" : [
{
"type" : "ClutterDragAction",
"signals" : [
{ "name" : "drag-end", "handler" : "on_drag_end" }
]
}
],
...
}
In order to do so, we use the Scriptable interface implementation and
add three new custom properties accepting an array; then we parse each
member of the array as a new object.
The marshallers we use for the signals are declared in a private header,
and it stands to reason that they should also be hidden in the shared
object by using the common '_' prefix. We are also using some direct
g_cclosure_marshal_* symbol from GLib, instead of consistently use the
clutter_marshal_* symbol.
It is often useful to determine if one actor is an ancestor of
another. Add a method to do that.
http://bugzilla.openedhand.com/show_bug.cgi?id=2162
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
Since ClutterEffect is an ActorMeta it should be possible to animate the
properties of named effects using the @effects syntax, just like it
happens for actions and constraints.
ClutterEffect is an abstract class that should be used to apply effects
on generic actors.
The ClutterEffect class just defines what an effect should implement; it
could be defined as an interface, but we might want to add some default
behavior dependent on the internal state at a later point.
The effect API applies to any actor, so we need to provide a way to
assign an effect to an actor, and let ClutterActor call the Effect
methods during the paint sequence.
Once an effect is attached to an actor we will perform the paint in this
order:
• Effect::pre_paint()
• Actor::paint signal emission
• Effect::post_paint()
Since an effect might collide with the Shader class, we either allow a
shader or an effect for the time being.
When getting the relative modelview matrix we need to reset it to the
stage's initial state or, at least, initialize it to the identity
matrix, instead of assuming we have an empty stack.
While this is totally fine (0 in the pointer context will be converted
in the right internal NULL representation, which could be a value with
some bits to 1), I believe it's clearer to use NULL in the pointer
context.
It seems that, in most case, it's more an overlook than a deliberate
choice to use FALSE/0 as NULL, eg. copying a _COGL_GET_CONTEXT (ctx, 0)
or a g_return_val_if_fail (cond, 0) from a function returning a
gboolean.
New virtual functions cannot go wherever they want, if we need to
preserve the ABI.
Also, the coding style should match the rest of ClutterActor and
Clutter's own coding style.
Added the implementation for clutter_actor_get_accessible, virtual
ClutterActor function, used to obtain the accessible object of
any ClutterActor.
As it is defined virtual, it would be possible to redefine it, so
any custom clutter actor could implement their accessibility object,
withouth relying totally on a accessibility implementation module.
See gtkiconview as example.
http://bugzilla.openedhand.com/show_bug.cgi?id=2070
The ClutterActor API should have modifier methods for adding, removing
and retrieving Actions and Constraints using the ClutterActorMeta:name
property - mostly, for convenience.
By implementing the newly added support for custom animatable
properties, we can allow addressing action and constraint properties
from ClutterAnimation and clutter_actor_animate().
The Constraint base, abstract class should be used to implement Actor
modifiers that affect the way an actor is sized or positioned inside a
fixed layout manager.
ClutterAction is an abstract class that should be used as the ancestor
for objects that change how an actor behaves when dealing with events
coming from user input.
Whenever we are warning inside ClutterActor we prefer the actor's name
to its type, if the name is set. The current code is made less readable
by the use of the ternary operator:
priv->name != NULL ? priv->name : G_OBJECT_TYPE_NAME (self)
This looks like a job for a simple convenience function.
For internal use we should have a get_stage_internal() variant that
avoids type checks and calls to public functions. The implementation
is trivial enough, and it will avoid (scene graph depth + 1) type
checks and (scene graph depth) function calls.
In 125bded81 some comments were introduced to ClutterTexture
complaining that it can have a Cogl texture before being
realized. Clutter always assumes that the single GL context is current
so there is no need to wait until the actor is realized before setting
a texture. This patch replaces the comments with clarification that
this should not be a problem.
The patch also changes the documentation about the realized state in
various places to clarify that it is acceptable to create any Cogl
resources before the actor is realized.
http://bugzilla.openedhand.com/show_bug.cgi?id=2075
The Actor's long description is a bit cluttered; it contains a section
on the actor's box semantics, on the transformation order and on the
event handling.
We should use <refsect2> tags to divide the Actor's description into
logically separated sections.
We should also add a section about the custom Scriptable properties that
ClutterActor defines, and the special handling of unit-based properties.
When emitting signals, one can mark arguments as being "static", ie an
indication this argument will not change during the signal emission.
This allows the signal marshalling code to create static GValues, in
this case not to copy the Color.
http://bugzilla.openedhand.com/show_bug.cgi?id=2073
We decide whether the paint() should be a real paint or a paint in pick
mode depending on the global pick_mode value. Using G_UNLIKELY() on an
operation that most likely is going to be executed once every frame is
going to blow a lot of cache lines and frak with the CPU branch
prediction. Not good.
Add clutter_actor_has_allocation(), a method meant to be used when
deciding whether to call clutter_actor_get_allocation_box() or any
of its wrappers.
The get_allocation_box() method will, in case the allocation is invalid,
perform a costly re-allocation cycle to ensure that the returned box
is valid. The has_allocation() method is meant to be used if we have an
actor calling get_allocation_box() from outside the place where the
allocation is always guaranteed to be valid.
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
Somebody somewhere decided it would be ok to define 'y1' as a global
function in math.h thus condemning us to repeatedly making commits to
fix these obnoxious compiler warnings about aliasing.
When printing out the property value during a ClutterScript debug run we
generate the value's content using g_strdup_value_contents() - though we
do it unconditionally. The contents might not be printed (they most
likely won't, actually) and will be freed afterwards. This is
unnecessary: we can allocate the contents string after checking if we're
going to print out the debug note, thus avoiding the whole
allocation/free cycle unless strictly needed.
* Add new clutter_geometry_union(), because writing union intersection
is harder than it looks. Fixes two problems with the inline code in
clutter_stage_glx_add_redraw_clip().
1) The ->x and ->y of were reassigned to before using them to
compute the new width and height.
2) since ClutterGeometry has unsigned width, x + width is unsigned,
and comparison goes wrong if either rectangle has a negative
x + width. (We fixed width for GdkRectangle to be signed for GTK+-2.0,
this is a potent source of bugs.)
* Use in clutter_stage_glx_add_redraw_clip()
* Account for the case where the incoming rectangle is empty, and don't
end up with the stage being entirely redrawn.
* Account for the case where the stage already has a degenerate
width and don't end up with redrawing only the new rectangle and not
the rest of the stage.
The better fix here for the second two problems is to stop using a 0
width to mean the entire stage, but this should work for now.
http://bugzilla.openedhand.com/show_bug.cgi?id=2040
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
The documentation and name of the get_transformation_matrix function
implies that 'matrix' is purely an out parameter. However it wasn't
initializing the matrix before calling the 'apply_transform' virtual
so it was basically just a wrapper for the virtual. The virtual
assumes the matrix parameter is in/out and applies the actor's
transformation on top of any existing transformations. This causes
unexpected semantics that are inconsistent with the documentation.
A new (internal only currently) API, _clutter_actor_queue_clipped_redraw
can be used to queue a redraw along with a clip rectangle in actor
coordinates. This clip rectangle propagates up to the stage and clutter
backend which may optionally use the information to optimize stage
redraws. The GLX backend in particular may scissor the next redraw to
the clip rectangle and use GLX_MESA_copy_sub_buffer to present the stage
subregion.
The intention is that any actors that can naturally determine the bounds
of updates should queue clipped redraws to reduce the cost of updating
small regions of the screen.
Notes:
» If GLX_MESA_copy_sub_buffer isn't available then the GLX backend
ignores any clip rectangles.
» queuing multiple clipped redraws will result in the bounding box of
each clip rectangle being used.
» If a clipped redraw has a height > 300 pixels then it's promoted into
a full stage redraw, so that the GPU doesn't end up blocking too long
waiting for the vsync to reach the optimal position to avoid tearing.
» Note: no empirical data was used to come up with this threshold so
we may need to tune this.
» Currently only ClutterX11TexturePixmap makes use of this new API. This
is done via a new "queue-damage-redraw" signal that is emitted when
the pixmap is updated. The default handler queues a clipped redraw
with the assumption that the pixmap is being painted as a rectangle
covering the actors transformed allocation. If you subclass
ClutterX11TexturePixmap and change how it's painted you now also
need to override the signal handler and queue your own redraw.
Technically this is a semantic break, but it's assumed that no one
is currently doing this.
This still leaves a few unsolved issues with regards to optimizing sub
stage redraws that need to be addressed in further work so this can only
be considered a stepping stone a this point:
» Because we have no reliable way to determine if the painting of any
given actor is being modified any optimizations implemented using
_clutter_actor_queue_redraw_with_clip must be overridable by a
subclass, and technically must be opt-in for existing classes to avoid
a change in semantics. E.g. consider that a user connects to the paint
signal for ClutterTexture and paints a circle instead of a rectangle.
In this case any original logic to queue clipped redraws would be
incorrect.
» Currently only the implementation of an actor has enough information
with which to queue clipped redraws. E.g. It is not possible for
generic code in clutter-actor.c to queue a clipped redraw when hiding
an actor because actors have no way to report a "paint box". (remember
actors can draw outside their allocation and actors with depth may
also be projected outside of their allocation)
» The current plan is to add a actor_class->get_paint_cuboid()
virtual so actors can report a bounding cube for everything they
would draw in their current state and use that to queue clipped
redraws against the stage by projecting the paint cube into stage
coordinates.
» Our heuristics for promoting clipped redraws into full redraws to
avoid blocking the GPU while we wait for the vsync need improving:
» vsync issues aren't relevant for redirected/composited applications
so they should use different heuristics. In this case we instead
need to trade off the cost of blitting when using glXCopySubBuffer
vs promoting to a full redraw and flipping instead.
* stage-min-size-rework:
docs: Update minimum size accessors
actor: Use the TOPLEVEL flag instead of a type check
[stage] Use min-width/height props for min size
Since using addresses that might change is something that finally
the FSF acknowledge as a plausible scenario (after changing address
twice), the license blurb in the source files should use the URI
for getting the license in case the library did not come with it.
Not that URIs cannot possibly change, but at least it's easier to
set up a redirection at the same place.
As a side note: this commit closes the oldes bug in Clutter's bug
report tool.
http://bugzilla.openedhand.com/show_bug.cgi?id=521
If the actor is an internal child of another actor then we should call
unparent() when destroying it, like clutter_actor_reparent() does;
otherwise we'll leak the actor, since the parent holds a reference to
it.
http://bugzilla.openedhand.com/show_bug.cgi?id=2009
Instead of shadowing these properties with different properties with the
same names on stage, actually use them. Behaviour should be identical,
except the minimum stage size can now be enforced by setting the
min-width/height properties as well as using the set_minimum_size
function.
Since the "internal" state is global, it will leak onto actors that you
didn't intend for it to, because it applies not just to the actors you
create, but also to any actors *they* create. Eg, if you have a dialog
box class, you might push/pop_internal around creating its buttons, so
that those buttons get marked as internal to the dialog box. But
ctx->internal_child will still be set during the *button*'s constructor
as well, and so, eg, the label and icon inside the button actor will
*also* be marked as internal children, even if that isn't what the
button class wanted.
The least intrusive change at this point is to make push_internal() and
pop_internal() two methods of the Actor class, and take a ClutterActor
pointer as the argument - thus moving the locality of the internal_child
counter to the Actor itself.
http://bugzilla.openedhand.com/show_bug.cgi?id=1990
Since get_paint_opacity() recurses through the hierarchy it might lead
to a lot of type checks while we walk the parent-child chain. We can
split the recursive function from the public entry point and perform the
type check just once.
This replaces code like this:
if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self);
with:
clutter_actor_queue_redraw (self);
clutter_actor_queue_redraw internally knows what can be optimized when
the actor is not visible, but it also knows that the queue_redraw signal
must always be sent in case a ClutterClone is cloning a hidden actor.
• Add the function name in the warning, since the text is the same in
both clutter_actor_raise() and clutter_actor_lower().
• If an actor has a name then prefer it to the type name.
Since we're allowing allocation cycles saying that calling
queue_relayout() inside an allocation cycle "is not allowed" is kind of
confusing. We should say that "it is not recommended".
* device-manager: (37 commits)
x11: Re-enable XI1 extension keyboards
x11: Always handle core device events before XI events
docs: Documentation fixes for DeviceManager
device-manager: Fix the signals definition
docs: Add sections for InputDevice and DeviceManager
docs: Add clutter_input_device_get_device_name()
tests: Print out the device details on motion
Always register core devices
device: Remove unused is_default member
win32: Experimental implementation of device support
tests: Print the device name, as well as its Id
x11: Fill out the :name property of the InputDevices
device: Add the :name property to InputDevice
x11: Store core devices on the X11 Backend singleton
device: Unset the cursor actor when leaving the stage
device: Add pointer actor getter
x11: Discard the LeaveNotify for off-stage ButtonRelease
device: Do not overwrite the stage for an InputDevice
event: Off-stage button releases have a click count of 1
event: Scroll events do not have click count
...
The :opacity property is defined using a GParamSpecUchar. This usually
leads to issues with language bindings that don't have an 'unsigned
char' type and that need to explicitly handle the conversion between
G_TYPE_UCHAR and G_TYPE_INT or G_TYPE_UINT.
The property definition already specifies an interval size of [0, 255]
on the values; more importantly, GObject already implicitly transforms
between G_TYPE_UCHAR and G_TYPE_UINT (the GValue transformation
functions are registered at type system initialization time) so
switching between a GParamSpecUchar and a GParamSpecUint should not be
an ABI break.
I have tested a simple program using the opacity property before and
after the change and I cannot see any run-time warnings related to this
issue.
UProf is a small library that aims to help applications/libraries provide
domain specific reports about performance. It currently provides high
precision timer primitives (rdtsc on x86) and simple counters, the ability
to link statistics between optional components at runtime and makes report
generation easy.
This adds initial accounting for:
- Total mainloop time
- Painting
- Picking
- Layouting
- Idle time
The timing done by uprof is of wall clock time. It's not based on stochastic
samples we simply sample a counter at the start and end. When dealing with
the complexities of GPU drivers and with various kinds of IO this form of
profiling can be quite enlightening as it will be able to represent where
your application is blocking unlike tools such as sysprof.
To enable uprof accounting you must configure Clutter with --enable-profile
and have uprof-0.2 installed from git://git.moblin.org/uprof
If you want to see a report of statistics when Clutter applications exit you
should export CLUTTER_PROFILE_OUTPUT_REPORT=1 before running them.
Just a final word of caution; this stuff is new and the manual nature of
adding uprof instrumentation means it is prone to some errors when modifying
code. This just means that when you question strange results don't rule out
a mistake in the instrumentation. Obviously though we hope the benfits out
weigh e.g. by focusing on very key stats and by having automatic reporting.
Currently, ClutterActor detects a relayout cycle (an actor causing a
relayout to be queued from within an allocate() function) and aborts
after printing out a warning. This might be a little bit too anal
retentive, and it currently breaks GTK+ embedding inside clutter-gtk
so we should probably relax the behaviour a bit. Now we just emit the
warning but we still go ahead with the relayout.
* animate-layout-manager:
layout-manager: Document the animation support
layout-manager: Rewind the timeline in begin_animation()
box-layout: Remove the allocations hash table
docs: Clean up the README file
layout: Let begin_animation() return the Alpha
box-layout: Add knobs for controlling animations
box-layout: Animate layout properties
layout: Add animation support to LayoutManager
Add ActorBox animation methods
ClutterActor checks, when destroying and reparenting, if the parent
actor implements the Container interface, and automatically calls the
remove() method to perform a clean removal.
Actors implementing Container, though, might have internal children;
that is, children that are not added through the Container API. It is
already possible to iterate through them using the Container API to
avoid breaking invariants - but calling clutter_actor_destroy() on
these children (even from the Container implementation, and thus outside
of Clutter's control) will either lead to leaks or to segmentation
faults.
Clutter needs a way to distinguish a clutter_actor_set_parent() done on
an internal child from one done on a "public" child; for this reason, a
push/pop pair of functions should be available to Actor implementations
to mark the section where they wish to add internal children:
➔ clutter_actor_push_internal ();
...
clutter_actor_set_parent (child1, parent);
clutter_actor_set_parent (child2, parent);
...
➔ clutter_actor_pop_internal ();
The set_parent() call will automatically set the newly added
INTERNAL_CHILD private flag on each child, and both
clutter_actor_destroy() and clutter_actor_unparent() will check for the
flag before deciding whether to call the Container's remove method.
ClutterActorBox should have an interpolate() method that allows to
compute the intermediate values between two states, given a progress
value, e.g.:
clutter_actor_box_interpolate (start, end, alpha, &result);
Another utility method, useful for layout managers, is a modifier
that clamps the members of the actor box to the nearest integer
value.
Some actor implementation might avoid imposing any layout on their
children. The Actor base class usually assumes some sort of layout
management is in place, so it will queue relayouts when, for instance,
an actor is shown or is hidden. If the parent of the actor does not
impose any layout, though, showing or hiding one of its children will
not affect the layout of the others.
An example of this kind of container is ClutterGroup.
By adding a new Actor flag, CLUTTER_ACTOR_NO_LAYOUT, and by making
the Group actor set it on itself, the Actor base class can now decide
whether or not to queue a relayout. The flag is not meant to be used
by application code, and should only be set when implementing a new
container.
http://bugzilla.openedhand.com/show_bug.cgi?id=1838
clutter_actor_get_preferred_width/height currently caches only one size
requests, for a given height / width.
It's common for a layout manager to call get_preferred_width with 2
different heights during the same allocation cycle. Typically once in
the size request, once in the allocation. If
clutter_actor_get_preferred_width is called
alternatively with 2 different for_height, the cache is totally
inefficient, and we end up always querying the actor size even
when the actor does not need a re-allocation.
http://bugzilla.openedhand.com/show_bug.cgi?id=1876
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
Every actor should have a property for retrieving (and setting) the
text direction.
The text direction is used to provide a consisten behaviour in both
left-to-right and right-to-left languages. For instance, ClutterText
should perform key navigation following text direction. Layout
managers should also take into account text direction to derive the
right packing order for their children.
cogl_clip_push, and cogl_clip_push_window_rect which are now deprecated were
used in various places internally so this just switches to using the
replacement functions.
If an actor calls directly or indirectly clutter_actor_queue_relayout()
on itself from within the allocate() implementation it will cause a
relayout cycle. This is usually a condition that should be checked by
ClutterActor and we should emit a warning if it is verified.
ClutterActor should check whether the current instance is being
destroyed and avoid performing operations like:
• queueing redraws
• queueing relayouts
It should also warn if the actor is being parented to an actor
currently being destroyed.
When showing a warning in the state checks we perform to verify that
the invariants are maintained when showing, mapping and realizing, we
should also print out the name of the actor failing the checks. If the
actor has no name, the GType name should be used as a fallback.
When an actor is hidden, the parent actor is not required to
size request or allocate it. (ClutterGroup does, but, for example,
NbtkBoxLayout doesn't.) This means that the
needs_width_request/needs_height_request/needs_allocate can be
stale when we go to show it again - they are set for the actor
but not the parent. Explicitly setting them to FALSE avoids
clutter_actor_relayout() improperly short-circuiting.
http://bugzilla.openedhand.com/show_bug.cgi?id=1831
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
The IN_DESTRUCTION flag is set around the unrealization and disposal of
the actor in clutter_actor_destroy() but is never unset (it's set twice
instead).
Reviewed-by: Emmanuele Bassi <ebassi@linux.intel.com>
ClutterClone bases its preferred size on the preferred size of
the source actor, so it needs to invalid its cached preferred
size when the preferred size of the source actor changes.
In order for this to work, we need to have notification when
the size of the source actor changes, so add a ::queue-relayout
signal to ClutterActor.
Then connect to this from ClutterClone and queue a relayout
on the clone when a relayout is queued on the source.
http://bugzilla.openedhand.com/show_bug.cgi?id=1755
Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
It is possible to unset the size of an actor specified with set_width()
and set_height() by using:
clutter_actor_set_size (actor, -1, -1);
Which works by unsetting the :min-*-set and the :natural-*-set properties.
Calling set_width(-1) and set_height(-1) separately, though, doesn't work
thus implicitly breaking the assumption that set_size() is nothing more
than set_width()+set_height(). This was obviously due to the face that
pre-1.0 set_width() and set_height() took an unsigned integer as an
argument.
ClutterActor parses positional and dimensional properties with a
custom deserializer. We need to:
- handle G_TYPE_INT64, the default integer type for JSON-GLib
- use G_TYPE_FLOAT for properties, since Actor switched to it
for the pixel-based ones
This makes ClutterScript work again.
The "catch all" warning for a the mapped invariant violation is too
generic: it doesn't tell you why the invariant was broken in case
we are trying to map an unparented actor - e.g. through a Clone.