|
Packit |
31ecd5 |
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
|
Packit |
31ecd5 |
#include <clutter/clutter.h>
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
typedef struct _FooActor FooActor;
|
|
Packit |
31ecd5 |
typedef struct _FooActorClass FooActorClass;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
struct _FooActorClass
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActorClass parent_class;
|
|
Packit |
31ecd5 |
};
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
struct _FooActor
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActor parent;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
guint8 last_paint_opacity;
|
|
Packit |
31ecd5 |
int paint_count;
|
|
Packit |
31ecd5 |
};
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
typedef struct
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActor *stage;
|
|
Packit |
31ecd5 |
FooActor *foo_actor;
|
|
Packit |
31ecd5 |
ClutterActor *parent_container;
|
|
Packit |
31ecd5 |
ClutterActor *container;
|
|
Packit |
31ecd5 |
ClutterActor *child;
|
|
Packit |
31ecd5 |
ClutterActor *unrelated_actor;
|
|
Packit |
31ecd5 |
gboolean was_painted;
|
|
Packit |
31ecd5 |
} Data;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
GType foo_actor_get_type (void) G_GNUC_CONST;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static gboolean group_has_overlaps;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
foo_actor_paint (ClutterActor *actor)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
FooActor *foo_actor = (FooActor *) actor;
|
|
Packit |
31ecd5 |
ClutterActorBox allocation;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
foo_actor->last_paint_opacity = clutter_actor_get_paint_opacity (actor);
|
|
Packit |
31ecd5 |
foo_actor->paint_count++;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
clutter_actor_get_allocation_box (actor, &allocation);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Paint a red rectangle with the right opacity */
|
|
Packit |
31ecd5 |
cogl_set_source_color4ub (255,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
foo_actor->last_paint_opacity);
|
|
Packit |
31ecd5 |
cogl_rectangle (allocation.x1,
|
|
Packit |
31ecd5 |
allocation.y1,
|
|
Packit |
31ecd5 |
allocation.x2,
|
|
Packit |
31ecd5 |
allocation.y2);
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static gboolean
|
|
Packit |
31ecd5 |
foo_actor_get_paint_volume (ClutterActor *actor,
|
|
Packit |
31ecd5 |
ClutterPaintVolume *volume)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
return clutter_paint_volume_set_from_allocation (volume, actor);
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static gboolean
|
|
Packit |
31ecd5 |
foo_actor_has_overlaps (ClutterActor *actor)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
return FALSE;
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
foo_actor_class_init (FooActorClass *klass)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
actor_class->paint = foo_actor_paint;
|
|
Packit |
31ecd5 |
actor_class->get_paint_volume = foo_actor_get_paint_volume;
|
|
Packit |
31ecd5 |
actor_class->has_overlaps = foo_actor_has_overlaps;
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
foo_actor_init (FooActor *self)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
typedef struct _FooGroup FooGroup;
|
|
Packit |
31ecd5 |
typedef struct _FooGroupClass FooGroupClass;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
struct _FooGroupClass
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActorClass parent_class;
|
|
Packit |
31ecd5 |
};
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
struct _FooGroup
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActor parent;
|
|
Packit |
31ecd5 |
};
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
GType foo_group_get_type (void);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
G_DEFINE_TYPE (FooGroup, foo_group, CLUTTER_TYPE_ACTOR)
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static gboolean
|
|
Packit |
31ecd5 |
foo_group_has_overlaps (ClutterActor *actor)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
return group_has_overlaps;
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
foo_group_class_init (FooGroupClass *klass)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
actor_class->has_overlaps = foo_group_has_overlaps;
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
foo_group_init (FooGroup *self)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
verify_results (Data *data,
|
|
Packit |
31ecd5 |
guint8 expected_color_red,
|
|
Packit |
31ecd5 |
guint8 expected_color_green,
|
|
Packit |
31ecd5 |
guint8 expected_color_blue,
|
|
Packit |
31ecd5 |
int expected_paint_count,
|
|
Packit |
31ecd5 |
int expected_paint_opacity)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
guchar *pixel;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data->foo_actor->paint_count = 0;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Read a pixel at the center of the to determine what color it
|
|
Packit |
31ecd5 |
painted. This should cause a redraw */
|
|
Packit |
31ecd5 |
pixel = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage),
|
|
Packit |
31ecd5 |
50, 50, /* x/y */
|
|
Packit |
31ecd5 |
1, 1 /* width/height */);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
g_assert_cmpint (expected_paint_count, ==, data->foo_actor->paint_count);
|
|
Packit |
31ecd5 |
g_assert_cmpint (expected_paint_opacity,
|
|
Packit |
31ecd5 |
==,
|
|
Packit |
31ecd5 |
data->foo_actor->last_paint_opacity);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
g_assert_cmpint (ABS ((int) expected_color_red - (int) pixel[0]), <=, 2);
|
|
Packit |
31ecd5 |
g_assert_cmpint (ABS ((int) expected_color_green - (int) pixel[1]), <=, 2);
|
|
Packit |
31ecd5 |
g_assert_cmpint (ABS ((int) expected_color_blue - (int) pixel[2]), <=, 2);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
g_free (pixel);
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
verify_redraw (Data *data, int expected_paint_count)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
GMainLoop *main_loop = g_main_loop_new (NULL, TRUE);
|
|
Packit |
31ecd5 |
guint paint_handler;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
paint_handler = g_signal_connect_data (data->stage,
|
|
Packit |
31ecd5 |
"paint",
|
|
Packit |
31ecd5 |
G_CALLBACK (g_main_loop_quit),
|
|
Packit |
31ecd5 |
main_loop,
|
|
Packit |
31ecd5 |
NULL,
|
|
Packit |
31ecd5 |
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Queue a redraw on the stage */
|
|
Packit |
31ecd5 |
clutter_actor_queue_redraw (data->stage);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data->foo_actor->paint_count = 0;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Wait for it to paint */
|
|
Packit |
31ecd5 |
g_main_loop_run (main_loop);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
g_signal_handler_disconnect (data->stage, paint_handler);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
g_assert_cmpint (data->foo_actor->paint_count, ==, expected_paint_count);
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static gboolean
|
|
Packit |
31ecd5 |
run_verify (gpointer user_data)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
Data *data = user_data;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
group_has_overlaps = FALSE;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* By default the actor shouldn't be redirected so the redraw should
|
|
Packit |
31ecd5 |
cause the actor to be painted */
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 0, 0,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Make the actor semi-transparent and verify the paint opacity */
|
|
Packit |
31ecd5 |
clutter_actor_set_opacity (data->container, 127);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 127, 127,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
127);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* With automatic redirect for opacity it shouldn't redirect if
|
|
Packit |
31ecd5 |
* has_overlaps returns FALSE; */
|
|
Packit |
31ecd5 |
clutter_actor_set_offscreen_redirect
|
|
Packit |
31ecd5 |
(data->container, CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 127, 127,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
127);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* We do a double check here to verify that the actor wasn't cached
|
|
Packit |
31ecd5 |
* during the last check. If it was cached then this check wouldn't
|
|
Packit |
31ecd5 |
* result in any foo-actor re-paint. */
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 127, 127,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
127);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* With automatic redirect for opacity it should redirect if
|
|
Packit |
31ecd5 |
* has_overlaps returns TRUE.
|
|
Packit |
31ecd5 |
* The first paint will still cause the actor to draw because
|
|
Packit |
31ecd5 |
* it needs to fill the cache first. It should be painted with full
|
|
Packit |
31ecd5 |
* opacity */
|
|
Packit |
31ecd5 |
group_has_overlaps = TRUE;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 127, 127,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* The second time the actor is painted it should be cached */
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 127, 127,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* We should be able to change the opacity without causing the actor
|
|
Packit |
31ecd5 |
to redraw */
|
|
Packit |
31ecd5 |
clutter_actor_set_opacity (data->container, 64);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 191, 191,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Changing it back to fully opaque should cause it not to go
|
|
Packit |
31ecd5 |
through the FBO so it will draw */
|
|
Packit |
31ecd5 |
clutter_actor_set_opacity (data->container, 255);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 0, 0,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Tell it to always redirect through the FBO. This should cause a
|
|
Packit |
31ecd5 |
paint of the actor because the last draw didn't go through the
|
|
Packit |
31ecd5 |
FBO */
|
|
Packit |
31ecd5 |
clutter_actor_set_offscreen_redirect (data->container,
|
|
Packit |
31ecd5 |
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 0, 0,
|
|
Packit |
31ecd5 |
1,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* We should be able to change the opacity without causing the actor
|
|
Packit |
31ecd5 |
to redraw */
|
|
Packit |
31ecd5 |
clutter_actor_set_opacity (data->container, 64);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 191, 191,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Even changing it back to fully opaque shouldn't cause a redraw */
|
|
Packit |
31ecd5 |
clutter_actor_set_opacity (data->container, 255);
|
|
Packit |
31ecd5 |
verify_results (data,
|
|
Packit |
31ecd5 |
255, 0, 0,
|
|
Packit |
31ecd5 |
0,
|
|
Packit |
31ecd5 |
255);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Queueing a redraw on the actor should cause a redraw */
|
|
Packit |
31ecd5 |
clutter_actor_queue_redraw (data->container);
|
|
Packit |
31ecd5 |
verify_redraw (data, 1);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Queueing a redraw on a child should cause a redraw */
|
|
Packit |
31ecd5 |
clutter_actor_queue_redraw (data->child);
|
|
Packit |
31ecd5 |
verify_redraw (data, 1);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Modifying the transformation on the parent should cause a
|
|
Packit |
31ecd5 |
redraw */
|
|
Packit |
31ecd5 |
clutter_actor_set_anchor_point (data->parent_container, 0, 1);
|
|
Packit |
31ecd5 |
verify_redraw (data, 1);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
/* Redrawing an unrelated actor shouldn't cause a redraw */
|
|
Packit |
31ecd5 |
clutter_actor_set_position (data->unrelated_actor, 0, 1);
|
|
Packit |
31ecd5 |
verify_redraw (data, 0);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data->was_painted = TRUE;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
return G_SOURCE_REMOVE;
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
static void
|
|
Packit |
31ecd5 |
actor_offscreen_redirect (void)
|
|
Packit |
31ecd5 |
{
|
|
Packit |
31ecd5 |
Data data;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
|
Packit |
31ecd5 |
return;
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data.stage = clutter_test_get_stage ();
|
|
Packit |
31ecd5 |
data.parent_container = clutter_actor_new ();
|
|
Packit |
31ecd5 |
data.container = g_object_new (foo_group_get_type (), NULL);
|
|
Packit |
31ecd5 |
data.foo_actor = g_object_new (foo_actor_get_type (), NULL);
|
|
Packit |
31ecd5 |
clutter_actor_set_size (CLUTTER_ACTOR (data.foo_actor), 100, 100);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
clutter_actor_add_child (data.container, CLUTTER_ACTOR (data.foo_actor));
|
|
Packit |
31ecd5 |
clutter_actor_add_child (data.parent_container, data.container);
|
|
Packit |
31ecd5 |
clutter_actor_add_child (data.stage, data.parent_container);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data.child = clutter_actor_new ();
|
|
Packit |
31ecd5 |
clutter_actor_set_size (data.child, 1, 1);
|
|
Packit |
31ecd5 |
clutter_actor_add_child (data.container, data.child);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
data.unrelated_actor = clutter_actor_new ();
|
|
Packit |
31ecd5 |
clutter_actor_set_size (data.child, 1, 1);
|
|
Packit |
31ecd5 |
clutter_actor_add_child (data.stage, data.unrelated_actor);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
clutter_actor_show (data.stage);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
|
Packit |
31ecd5 |
run_verify,
|
|
Packit |
31ecd5 |
&data,
|
|
Packit |
31ecd5 |
NULL);
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
while (!data.was_painted)
|
|
Packit |
31ecd5 |
g_main_context_iteration (NULL, FALSE);
|
|
Packit |
31ecd5 |
}
|
|
Packit |
31ecd5 |
|
|
Packit |
31ecd5 |
CLUTTER_TEST_SUITE (
|
|
Packit |
31ecd5 |
CLUTTER_TEST_UNIT ("/actor/offscreen/redirect", actor_offscreen_redirect)
|
|
Packit |
31ecd5 |
)
|