Use signals instead of onscreen framebuffer frame callbacks

CoglFrameInfo is a frame info container associated with a single
onscreen framebuffer. The clutter stage will eventually support drawing
a stage frame with multiple onscreen framebuffers, thus needs its own
frame info container.

This patch introduces a new stage signal 'presented' and a accompaning
ClutterFrameInfo and adapts the stage windows and past onscreen frame
callbacks users to use the signal and new info container.

https://bugzilla.gnome.org/show_bug.cgi?id=768976
This commit is contained in:
Jonas Ådahl
2016-06-08 13:07:09 +08:00
parent 92341e7c30
commit 28a898a22f
20 changed files with 166 additions and 154 deletions

View File

@@ -37,11 +37,6 @@ void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
CLUTTER_AVAILABLE_IN_MUTTER
gboolean _clutter_get_sync_to_vblank (void);
CLUTTER_AVAILABLE_IN_MUTTER
CoglFrameClosure *clutter_stage_add_frame_callback (ClutterStage *stage,
CoglFrameCallback callback,
gpointer user_data);
CLUTTER_AVAILABLE_IN_MUTTER
int64_t clutter_stage_get_frame_counter (ClutterStage *stage);

View File

@@ -125,6 +125,10 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
void _clutter_stage_set_scale_factor (ClutterStage *stage,
int factor);
void _clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@@ -338,25 +338,6 @@ _clutter_stage_window_get_views (ClutterStageWindow *window)
return iface->get_views (window);
}
CoglFrameClosure *
_clutter_stage_window_set_frame_callback (ClutterStageWindow *window,
CoglFrameCallback callback,
gpointer user_data)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
return iface->set_frame_callback (window, callback, user_data);
}
void
_clutter_stage_window_remove_frame_callback (ClutterStageWindow *window,
CoglFrameClosure *closure)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
iface->remove_frame_callback (window, closure);
}
void
_clutter_stage_window_finish_frame (ClutterStageWindow *window)
{

View File

@@ -87,11 +87,6 @@ struct _ClutterStageWindowIface
int factor);
int (* get_scale_factor) (ClutterStageWindow *stage_window);
GList *(* get_views) (ClutterStageWindow *stage_window);
CoglFrameClosure *(* set_frame_callback) (ClutterStageWindow *stage_window,
CoglFrameCallback callback,
gpointer user_data);
void (* remove_frame_callback) (ClutterStageWindow *stage_window,
CoglFrameClosure *closure);
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
void (* finish_frame) (ClutterStageWindow *stage_window);
};
@@ -151,13 +146,6 @@ int _clutter_stage_window_get_scale_factor (ClutterStageWin
GList * _clutter_stage_window_get_views (ClutterStageWindow *window);
CoglFrameClosure *_clutter_stage_window_set_frame_callback (ClutterStageWindow *window,
CoglFrameCallback callback,
gpointer user_data);
void _clutter_stage_window_remove_frame_callback (ClutterStageWindow *stage_winow,
CoglFrameClosure *closure);
void _clutter_stage_window_finish_frame (ClutterStageWindow *window);
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);

View File

@@ -190,6 +190,7 @@ enum
DEACTIVATE,
DELETE_EVENT,
AFTER_PAINT,
PRESENTED,
LAST_SIGNAL
};
@@ -2167,6 +2168,21 @@ clutter_stage_class_init (ClutterStageClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* ClutterStage::presented: (skip)
* @stage: the stage that received the event
* @frame_event: a #CoglFrameEvent
* @frame_info: a #ClutterFrameInfo
*/
stage_signals[PRESENTED] =
g_signal_new (I_("presented"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2,
G_TYPE_INT, G_TYPE_POINTER);
klass->fullscreen = clutter_stage_real_fullscreen;
klass->activate = clutter_stage_real_activate;
klass->deactivate = clutter_stage_real_deactivate;
@@ -4628,19 +4644,6 @@ _clutter_stage_set_scale_factor (ClutterStage *stage,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
}
CoglFrameClosure *
clutter_stage_add_frame_callback (ClutterStage *stage,
CoglFrameCallback callback,
gpointer user_data)
{
ClutterStageWindow *stage_window;
stage_window = _clutter_stage_get_window (stage);
return _clutter_stage_window_set_frame_callback (stage_window,
callback,
user_data);
}
int64_t
clutter_stage_get_frame_counter (ClutterStage *stage)
{
@@ -4649,3 +4652,12 @@ clutter_stage_get_frame_counter (ClutterStage *stage)
stage_window = _clutter_stage_get_window (stage);
return _clutter_stage_window_get_frame_counter (stage_window);
}
void
_clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info)
{
g_signal_emit (stage, stage_signals[PRESENTED], 0,
(int) frame_event, frame_info);
}

View File

@@ -135,6 +135,16 @@ struct _ClutterFog
gfloat z_far;
};
/**
* ClutterFrameInfo: (skip)
*/
struct _ClutterFrameInfo
{
int64_t frame_counter;
int64_t presentation_time;
float refresh_rate;
};
CLUTTER_AVAILABLE_IN_ALL
GType clutter_perspective_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_IN_1_10

View File

@@ -51,6 +51,7 @@ G_BEGIN_DECLS
typedef struct _ClutterActor ClutterActor;
typedef struct _ClutterStage ClutterStage;
typedef struct _ClutterFrameInfo ClutterFrameInfo;
typedef struct _ClutterContainer ClutterContainer; /* dummy */
typedef struct _ClutterChildMeta ClutterChildMeta;
typedef struct _ClutterLayoutMeta ClutterLayoutMeta;

View File

@@ -81,24 +81,15 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl);
if (stage_cogl->frame_closure != NULL)
{
_clutter_stage_window_remove_frame_callback (stage_window,
stage_cogl->frame_closure);
stage_cogl->frame_closure = NULL;
}
}
static void
frame_cb (CoglOnscreen *onscreen,
CoglFrameEvent event,
CoglFrameInfo *info,
void *user_data)
void
_clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info)
{
ClutterStageCogl *stage_cogl = user_data;
if (event == COGL_FRAME_EVENT_SYNC)
if (frame_event == COGL_FRAME_EVENT_SYNC)
{
/* Early versions of the swap_event implementation in Mesa
* deliver BufferSwapComplete event when not selected for,
@@ -112,13 +103,14 @@ frame_cb (CoglOnscreen *onscreen,
if (stage_cogl->pending_swaps > 0)
stage_cogl->pending_swaps--;
}
else if (event == COGL_FRAME_EVENT_COMPLETE)
else if (frame_event == COGL_FRAME_EVENT_COMPLETE)
{
gint64 presentation_time_cogl = cogl_frame_info_get_presentation_time (info);
gint64 presentation_time_cogl = frame_info->presentation_time;
if (presentation_time_cogl != 0)
{
CoglContext *context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (onscreen));
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 ();
@@ -126,8 +118,10 @@ frame_cb (CoglOnscreen *onscreen,
now + (presentation_time_cogl - current_time_cogl) / 1000;
}
stage_cogl->refresh_rate = cogl_frame_info_get_refresh_rate (info);
stage_cogl->refresh_rate = frame_info->refresh_rate;
}
_clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info);
}
static gboolean
@@ -148,10 +142,6 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
return FALSE;
}
stage_cogl->frame_closure =
_clutter_stage_window_set_frame_callback (stage_window,
frame_cb, stage_window);
return TRUE;
}

View File

@@ -51,8 +51,6 @@ struct _ClutterStageCogl
float refresh_rate;
int pending_swaps;
CoglFrameClosure *frame_closure;
gint64 last_presentation_time;
gint64 update_time;
@@ -78,6 +76,11 @@ struct _ClutterStageCoglClass
CLUTTER_AVAILABLE_IN_MUTTER
GType _clutter_stage_cogl_get_type (void) G_GNUC_CONST;
CLUTTER_AVAILABLE_IN_MUTTER
void _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info);
G_END_DECLS
#endif /* __CLUTTER_STAGE_COGL_H__ */

View File

@@ -443,6 +443,13 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
if (cogl_get_draw_framebuffer () == COGL_FRAMEBUFFER (stage_x11->onscreen))
_clutter_backend_reset_cogl_framebuffer (stage_cogl->backend);
if (stage_x11->frame_closure)
{
cogl_onscreen_remove_frame_callback (stage_x11->onscreen,
stage_x11->frame_closure);
stage_x11->frame_closure = NULL;
}
clutter_stage_window_parent_iface->unrealize (stage_window);
g_list_free (stage_x11->legacy_views);
@@ -604,6 +611,23 @@ stage_events_device_added (ClutterDeviceManager *device_manager,
stage_cogl->wrapper);
}
static void
frame_cb (CoglOnscreen *onscreen,
CoglFrameEvent frame_event,
CoglFrameInfo *frame_info,
void *user_data)
{
ClutterStageCogl *stage_cogl = user_data;
ClutterFrameInfo clutter_frame_info = {
.frame_counter = cogl_frame_info_get_frame_counter (frame_info),
.presentation_time = cogl_frame_info_get_presentation_time (frame_info),
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info)
};
_clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info);
}
static gboolean
clutter_stage_x11_realize (ClutterStageWindow *stage_window)
{
@@ -628,6 +652,14 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
stage_x11->onscreen = cogl_onscreen_new (backend->cogl_context, width, height);
cogl_onscreen_set_swap_throttled (stage_x11->onscreen,
_clutter_get_sync_to_vblank ());
stage_x11->frame_closure =
cogl_onscreen_add_frame_callback (stage_x11->onscreen,
frame_cb,
stage_cogl,
NULL);
if (stage_x11->legacy_view)
g_object_set (G_OBJECT (stage_x11->legacy_view),
"framebuffer", stage_x11->onscreen,
@@ -929,31 +961,6 @@ clutter_stage_x11_get_views (ClutterStageWindow *stage_window)
return stage_x11->legacy_views;
}
static CoglFrameClosure *
clutter_stage_x11_set_frame_callback (ClutterStageWindow *stage_window,
CoglFrameCallback callback,
gpointer user_data)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
cogl_onscreen_set_swap_throttled (stage_x11->onscreen,
_clutter_get_sync_to_vblank ());
return cogl_onscreen_add_frame_callback (stage_x11->onscreen,
callback,
user_data,
NULL);
}
static void
clutter_stage_x11_remove_frame_callback (ClutterStageWindow *stage_window,
CoglFrameClosure *closure)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
cogl_onscreen_remove_frame_callback (stage_x11->onscreen, closure);
}
static int64_t
clutter_stage_x11_get_frame_counter (ClutterStageWindow *stage_window)
{
@@ -1037,8 +1044,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->set_scale_factor = clutter_stage_x11_set_scale_factor;
iface->get_scale_factor = clutter_stage_x11_get_scale_factor;
iface->get_views = clutter_stage_x11_get_views;
iface->set_frame_callback = clutter_stage_x11_set_frame_callback;
iface->remove_frame_callback = clutter_stage_x11_remove_frame_callback;
iface->get_frame_counter = clutter_stage_x11_get_frame_counter;
}

View File

@@ -61,6 +61,8 @@ struct _ClutterStageX11
ClutterStageView *legacy_view;
GList *legacy_views;
CoglFrameClosure *frame_closure;
gchar *title;
guint clipped_redraws_cool_off;