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.