clutter: Introduce ClutterFrame
ClutterFrame aims to carry information valid during dispatching a frame. A frame may or may not include redrawing, but will always end with a result. A asynchronous page flip, for example, will result in a CLUTTER_FRAME_RESULT_PENDING_PRESENTED, while a frame that only dispatched events etc will result in CLUTTER_FRAME_RESULT_IDLE. Instead of this being implicit, make the ClutterStageWindow implementation handle this itself. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
parent
9c500f23e4
commit
72b35e07c0
33
clutter/clutter/clutter-frame-private.h
Normal file
33
clutter/clutter/clutter-frame-private.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLUTTER_FRAME_PRIVATE_H
|
||||||
|
#define CLUTTER_FRAME_PRIVATE_H
|
||||||
|
|
||||||
|
#include "clutter/clutter-frame.h"
|
||||||
|
|
||||||
|
struct _ClutterFrame
|
||||||
|
{
|
||||||
|
gboolean has_result;
|
||||||
|
ClutterFrameResult result;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
|
||||||
|
|
||||||
|
ClutterFrameResult clutter_frame_get_result (ClutterFrame *frame);
|
||||||
|
|
||||||
|
#endif /* CLUTTER_FRAME_PRIVATE_H */
|
42
clutter/clutter/clutter-frame.c
Normal file
42
clutter/clutter/clutter-frame.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clutter/clutter-frame-private.h"
|
||||||
|
|
||||||
|
ClutterFrameResult
|
||||||
|
clutter_frame_get_result (ClutterFrame *frame)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (frame->has_result, CLUTTER_FRAME_RESULT_IDLE);
|
||||||
|
|
||||||
|
return frame->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_frame_has_result (ClutterFrame *frame)
|
||||||
|
{
|
||||||
|
return frame->has_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_frame_set_result (ClutterFrame *frame,
|
||||||
|
ClutterFrameResult result)
|
||||||
|
{
|
||||||
|
g_warn_if_fail (!frame->has_result);
|
||||||
|
|
||||||
|
frame->result = result;
|
||||||
|
frame->has_result = TRUE;
|
||||||
|
}
|
36
clutter/clutter/clutter-frame.h
Normal file
36
clutter/clutter/clutter-frame.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLUTTER_FRAME_H
|
||||||
|
#define CLUTTER_FRAME_H
|
||||||
|
|
||||||
|
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||||
|
#error "Only <clutter/clutter.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "clutter/clutter-frame-clock.h"
|
||||||
|
|
||||||
|
typedef struct _ClutterFrame ClutterFrame;
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
void clutter_frame_set_result (ClutterFrame *frame,
|
||||||
|
ClutterFrameResult result);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
gboolean clutter_frame_has_result (ClutterFrame *frame);
|
||||||
|
|
||||||
|
#endif /* CLUTTER_FRAME_H */
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "clutter/clutter-damage-history.h"
|
#include "clutter/clutter-damage-history.h"
|
||||||
#include "clutter/clutter-frame-clock.h"
|
#include "clutter/clutter-frame-clock.h"
|
||||||
|
#include "clutter/clutter-frame-private.h"
|
||||||
#include "clutter/clutter-private.h"
|
#include "clutter/clutter-private.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
#include "clutter/clutter-stage-private.h"
|
#include "clutter/clutter-stage-private.h"
|
||||||
@ -1076,7 +1077,7 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|||||||
ClutterStage *stage = priv->stage;
|
ClutterStage *stage = priv->stage;
|
||||||
ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
|
ClutterStageWindow *stage_window = _clutter_stage_get_window (stage);
|
||||||
g_autoptr (GSList) devices = NULL;
|
g_autoptr (GSList) devices = NULL;
|
||||||
ClutterFrameResult result;
|
ClutterFrame frame;
|
||||||
|
|
||||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||||
return CLUTTER_FRAME_RESULT_IDLE;
|
return CLUTTER_FRAME_RESULT_IDLE;
|
||||||
@ -1096,29 +1097,25 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|||||||
|
|
||||||
devices = clutter_stage_find_updated_devices (stage);
|
devices = clutter_stage_find_updated_devices (stage);
|
||||||
|
|
||||||
|
frame = CLUTTER_FRAME_INIT;
|
||||||
|
|
||||||
if (clutter_stage_view_has_redraw_clip (view))
|
if (clutter_stage_view_has_redraw_clip (view))
|
||||||
{
|
{
|
||||||
clutter_stage_emit_before_paint (stage, view);
|
clutter_stage_emit_before_paint (stage, view);
|
||||||
|
|
||||||
_clutter_stage_window_redraw_view (stage_window, view);
|
_clutter_stage_window_redraw_view (stage_window, view, &frame);
|
||||||
|
|
||||||
clutter_stage_emit_after_paint (stage, view);
|
clutter_stage_emit_after_paint (stage, view);
|
||||||
|
|
||||||
result = CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = CLUTTER_FRAME_RESULT_IDLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_clutter_stage_window_finish_frame (stage_window, view);
|
_clutter_stage_window_finish_frame (stage_window, view, &frame);
|
||||||
|
|
||||||
clutter_stage_update_devices (stage, devices);
|
clutter_stage_update_devices (stage, devices);
|
||||||
|
|
||||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
||||||
clutter_stage_emit_after_update (stage, view);
|
clutter_stage_emit_after_update (stage, view);
|
||||||
|
|
||||||
return result;
|
return clutter_frame_get_result (&frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ClutterFrameListenerIface frame_clock_listener_iface = {
|
static const ClutterFrameListenerIface frame_clock_listener_iface = {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include "clutter-actor.h"
|
#include "clutter-actor.h"
|
||||||
|
#include "clutter-frame.h"
|
||||||
#include "clutter-stage-window.h"
|
#include "clutter-stage-window.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
|
|
||||||
@ -104,11 +105,12 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window,
|
|||||||
|
|
||||||
void
|
void
|
||||||
_clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
_clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||||
ClutterStageView *view)
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame)
|
||||||
{
|
{
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||||
|
|
||||||
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view);
|
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -135,12 +137,19 @@ _clutter_stage_window_get_views (ClutterStageWindow *window)
|
|||||||
|
|
||||||
void
|
void
|
||||||
_clutter_stage_window_finish_frame (ClutterStageWindow *window,
|
_clutter_stage_window_finish_frame (ClutterStageWindow *window,
|
||||||
ClutterStageView *view)
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame)
|
||||||
{
|
{
|
||||||
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||||
|
|
||||||
if (iface->finish_frame)
|
if (iface->finish_frame)
|
||||||
iface->finish_frame (window, view);
|
{
|
||||||
|
iface->finish_frame (window, view, frame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clutter_frame_has_result (frame))
|
||||||
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
|
@ -45,14 +45,16 @@ struct _ClutterStageWindowInterface
|
|||||||
cairo_rectangle_int_t *geometry);
|
cairo_rectangle_int_t *geometry);
|
||||||
|
|
||||||
void (* redraw_view) (ClutterStageWindow *stage_window,
|
void (* redraw_view) (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *view);
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame);
|
||||||
|
|
||||||
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
|
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
|
||||||
|
|
||||||
GList *(* get_views) (ClutterStageWindow *stage_window);
|
GList *(* get_views) (ClutterStageWindow *stage_window);
|
||||||
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
|
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
|
||||||
void (* finish_frame) (ClutterStageWindow *stage_window,
|
void (* finish_frame) (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *view);
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
|
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
|
||||||
@ -80,14 +82,16 @@ void _clutter_stage_window_set_accept_focus (ClutterStageWin
|
|||||||
gboolean accept_focus);
|
gboolean accept_focus);
|
||||||
|
|
||||||
void _clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
void _clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||||
ClutterStageView *view);
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame);
|
||||||
|
|
||||||
gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window);
|
gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window);
|
||||||
|
|
||||||
GList * _clutter_stage_window_get_views (ClutterStageWindow *window);
|
GList * _clutter_stage_window_get_views (ClutterStageWindow *window);
|
||||||
|
|
||||||
void _clutter_stage_window_finish_frame (ClutterStageWindow *window,
|
void _clutter_stage_window_finish_frame (ClutterStageWindow *window,
|
||||||
ClutterStageView *view);
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame);
|
||||||
|
|
||||||
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);
|
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ G_BEGIN_DECLS
|
|||||||
typedef struct _ClutterActor ClutterActor;
|
typedef struct _ClutterActor ClutterActor;
|
||||||
|
|
||||||
typedef struct _ClutterStage ClutterStage;
|
typedef struct _ClutterStage ClutterStage;
|
||||||
|
typedef struct _ClutterFrame ClutterFrame;
|
||||||
typedef struct _ClutterFrameInfo ClutterFrameInfo;
|
typedef struct _ClutterFrameInfo ClutterFrameInfo;
|
||||||
typedef struct _ClutterContainer ClutterContainer; /* dummy */
|
typedef struct _ClutterContainer ClutterContainer; /* dummy */
|
||||||
typedef struct _ClutterChildMeta ClutterChildMeta;
|
typedef struct _ClutterChildMeta ClutterChildMeta;
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include "clutter-fixed-layout.h"
|
#include "clutter-fixed-layout.h"
|
||||||
#include "clutter-flow-layout.h"
|
#include "clutter-flow-layout.h"
|
||||||
#include "clutter-frame-clock.h"
|
#include "clutter-frame-clock.h"
|
||||||
|
#include "clutter-frame.h"
|
||||||
#include "clutter-gesture-action.h"
|
#include "clutter-gesture-action.h"
|
||||||
#include "clutter-grid-layout.h"
|
#include "clutter-grid-layout.h"
|
||||||
#include "clutter-image.h"
|
#include "clutter-image.h"
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-enum-types.h"
|
#include "clutter-enum-types.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
|
#include "clutter-frame.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-stage-private.h"
|
#include "clutter-stage-private.h"
|
||||||
@ -693,7 +694,8 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *view)
|
ClutterStageView *view,
|
||||||
|
ClutterFrame *frame)
|
||||||
{
|
{
|
||||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
g_autoptr (CoglScanout) scanout = NULL;
|
g_autoptr (CoglScanout) scanout = NULL;
|
||||||
@ -710,6 +712,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
clutter_stage_cogl_redraw_view_primary (stage_cogl, view);
|
clutter_stage_cogl_redraw_view_primary (stage_cogl, view);
|
||||||
|
|
||||||
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -37,6 +37,7 @@ clutter_headers = [
|
|||||||
'clutter-fixed-layout.h',
|
'clutter-fixed-layout.h',
|
||||||
'clutter-flow-layout.h',
|
'clutter-flow-layout.h',
|
||||||
'clutter-frame-clock.h',
|
'clutter-frame-clock.h',
|
||||||
|
'clutter-frame.h',
|
||||||
'clutter-gesture-action.h',
|
'clutter-gesture-action.h',
|
||||||
'clutter-grid-layout.h',
|
'clutter-grid-layout.h',
|
||||||
'clutter-image.h',
|
'clutter-image.h',
|
||||||
@ -125,6 +126,7 @@ clutter_sources = [
|
|||||||
'clutter-flatten-effect.c',
|
'clutter-flatten-effect.c',
|
||||||
'clutter-flow-layout.c',
|
'clutter-flow-layout.c',
|
||||||
'clutter-frame-clock.c',
|
'clutter-frame-clock.c',
|
||||||
|
'clutter-frame.c',
|
||||||
'clutter-gesture-action.c',
|
'clutter-gesture-action.c',
|
||||||
'clutter-graphene.c',
|
'clutter-graphene.c',
|
||||||
'clutter-grid-layout.c',
|
'clutter-grid-layout.c',
|
||||||
@ -194,6 +196,7 @@ clutter_private_headers = [
|
|||||||
'clutter-effect-private.h',
|
'clutter-effect-private.h',
|
||||||
'clutter-event-private.h',
|
'clutter-event-private.h',
|
||||||
'clutter-flatten-effect.h',
|
'clutter-flatten-effect.h',
|
||||||
|
'clutter-frame-private.h',
|
||||||
'clutter-graphene.h',
|
'clutter-graphene.h',
|
||||||
'clutter-gesture-action-private.h',
|
'clutter-gesture-action-private.h',
|
||||||
'clutter-id-pool.h',
|
'clutter-id-pool.h',
|
||||||
|
@ -107,12 +107,16 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
meta_stage_native_finish_frame (ClutterStageWindow *stage_window,
|
meta_stage_native_finish_frame (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *stage_view)
|
ClutterStageView *stage_view,
|
||||||
|
ClutterFrame *frame)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
|
||||||
meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer));
|
meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer));
|
||||||
|
|
||||||
|
if (!clutter_frame_has_result (frame))
|
||||||
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -159,7 +159,8 @@ draw_view (MetaStageX11Nested *stage_nested,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window,
|
meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *stage_view)
|
ClutterStageView *stage_view,
|
||||||
|
ClutterFrame *frame)
|
||||||
{
|
{
|
||||||
MetaStageX11Nested *stage_nested = META_STAGE_X11_NESTED (stage_window);
|
MetaStageX11Nested *stage_nested = META_STAGE_X11_NESTED (stage_window);
|
||||||
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
|
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
|
||||||
@ -196,6 +197,9 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window,
|
|||||||
|
|
||||||
frame_info = cogl_frame_info_new (0);
|
frame_info = cogl_frame_info_new (0);
|
||||||
cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info);
|
cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info);
|
||||||
|
|
||||||
|
if (!clutter_frame_has_result (frame))
|
||||||
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user