From 72b35e07c027c69048a1211ca987b3a05f0eb79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 9 Oct 2020 18:16:16 +0200 Subject: [PATCH] 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: --- clutter/clutter/clutter-frame-private.h | 33 +++++++++++++++ clutter/clutter/clutter-frame.c | 42 +++++++++++++++++++ clutter/clutter/clutter-frame.h | 36 ++++++++++++++++ clutter/clutter/clutter-stage-view.c | 17 ++++---- clutter/clutter/clutter-stage-window.c | 17 ++++++-- clutter/clutter/clutter-stage-window.h | 12 ++++-- clutter/clutter/clutter-types.h | 1 + clutter/clutter/clutter.h | 1 + clutter/clutter/cogl/clutter-stage-cogl.c | 6 ++- clutter/clutter/meson.build | 3 ++ src/backends/native/meta-stage-native.c | 6 ++- .../x11/nested/meta-stage-x11-nested.c | 6 ++- 12 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 clutter/clutter/clutter-frame-private.h create mode 100644 clutter/clutter/clutter-frame.c create mode 100644 clutter/clutter/clutter-frame.h diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h new file mode 100644 index 000000000..e0088564f --- /dev/null +++ b/clutter/clutter/clutter-frame-private.h @@ -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 . + */ + +#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 */ diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c new file mode 100644 index 000000000..3c708da9d --- /dev/null +++ b/clutter/clutter/clutter-frame.c @@ -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 . + */ + +#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; +} diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h new file mode 100644 index 000000000..d3608e81c --- /dev/null +++ b/clutter/clutter/clutter-frame.h @@ -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 . + */ + +#ifndef CLUTTER_FRAME_H +#define CLUTTER_FRAME_H + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only 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 */ diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 2b12b93ed..81662de06 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -25,6 +25,7 @@ #include "clutter/clutter-damage-history.h" #include "clutter/clutter-frame-clock.h" +#include "clutter/clutter-frame-private.h" #include "clutter/clutter-private.h" #include "clutter/clutter-mutter.h" #include "clutter/clutter-stage-private.h" @@ -1076,7 +1077,7 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, ClutterStage *stage = priv->stage; ClutterStageWindow *stage_window = _clutter_stage_get_window (stage); g_autoptr (GSList) devices = NULL; - ClutterFrameResult result; + ClutterFrame frame; if (CLUTTER_ACTOR_IN_DESTRUCTION (stage)) return CLUTTER_FRAME_RESULT_IDLE; @@ -1096,29 +1097,25 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, devices = clutter_stage_find_updated_devices (stage); + frame = CLUTTER_FRAME_INIT; + if (clutter_stage_view_has_redraw_clip (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); - - 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_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT); clutter_stage_emit_after_update (stage, view); - return result; + return clutter_frame_get_result (&frame); } static const ClutterFrameListenerIface frame_clock_listener_iface = { diff --git a/clutter/clutter/clutter-stage-window.c b/clutter/clutter/clutter-stage-window.c index 2d3192df0..5f7c48967 100644 --- a/clutter/clutter/clutter-stage-window.c +++ b/clutter/clutter/clutter-stage-window.c @@ -3,6 +3,7 @@ #include #include "clutter-actor.h" +#include "clutter-frame.h" #include "clutter-stage-window.h" #include "clutter-private.h" @@ -104,11 +105,12 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window, void _clutter_stage_window_redraw_view (ClutterStageWindow *window, - ClutterStageView *view) + ClutterStageView *view, + ClutterFrame *frame) { 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 @@ -135,12 +137,19 @@ _clutter_stage_window_get_views (ClutterStageWindow *window) void _clutter_stage_window_finish_frame (ClutterStageWindow *window, - ClutterStageView *view) + ClutterStageView *view, + ClutterFrame *frame) { ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); 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 diff --git a/clutter/clutter/clutter-stage-window.h b/clutter/clutter/clutter-stage-window.h index 0f2d5bc28..b1ebd2bad 100644 --- a/clutter/clutter/clutter-stage-window.h +++ b/clutter/clutter/clutter-stage-window.h @@ -45,14 +45,16 @@ struct _ClutterStageWindowInterface cairo_rectangle_int_t *geometry); void (* redraw_view) (ClutterStageWindow *stage_window, - ClutterStageView *view); + ClutterStageView *view, + ClutterFrame *frame); gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window); GList *(* get_views) (ClutterStageWindow *stage_window); int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); void (* finish_frame) (ClutterStageWindow *stage_window, - ClutterStageView *view); + ClutterStageView *view, + ClutterFrame *frame); }; ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); @@ -80,14 +82,16 @@ void _clutter_stage_window_set_accept_focus (ClutterStageWin gboolean accept_focus); void _clutter_stage_window_redraw_view (ClutterStageWindow *window, - ClutterStageView *view); + ClutterStageView *view, + ClutterFrame *frame); gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window); GList * _clutter_stage_window_get_views (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); diff --git a/clutter/clutter/clutter-types.h b/clutter/clutter/clutter-types.h index 1453eaaad..569e36604 100644 --- a/clutter/clutter/clutter-types.h +++ b/clutter/clutter/clutter-types.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS typedef struct _ClutterActor ClutterActor; typedef struct _ClutterStage ClutterStage; +typedef struct _ClutterFrame ClutterFrame; typedef struct _ClutterFrameInfo ClutterFrameInfo; typedef struct _ClutterContainer ClutterContainer; /* dummy */ typedef struct _ClutterChildMeta ClutterChildMeta; diff --git a/clutter/clutter/clutter.h b/clutter/clutter/clutter.h index d09f8afed..9b97cfc9e 100644 --- a/clutter/clutter/clutter.h +++ b/clutter/clutter/clutter.h @@ -64,6 +64,7 @@ #include "clutter-fixed-layout.h" #include "clutter-flow-layout.h" #include "clutter-frame-clock.h" +#include "clutter-frame.h" #include "clutter-gesture-action.h" #include "clutter-grid-layout.h" #include "clutter-image.h" diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c index ffc13bad7..02b13781a 100644 --- a/clutter/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/clutter/cogl/clutter-stage-cogl.c @@ -43,6 +43,7 @@ #include "clutter-event.h" #include "clutter-enum-types.h" #include "clutter-feature.h" +#include "clutter-frame.h" #include "clutter-main.h" #include "clutter-private.h" #include "clutter-stage-private.h" @@ -693,7 +694,8 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl, static void clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, - ClutterStageView *view) + ClutterStageView *view, + ClutterFrame *frame) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); 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_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } static void diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build index 4b617bd98..9f20d7ba3 100644 --- a/clutter/clutter/meson.build +++ b/clutter/clutter/meson.build @@ -37,6 +37,7 @@ clutter_headers = [ 'clutter-fixed-layout.h', 'clutter-flow-layout.h', 'clutter-frame-clock.h', + 'clutter-frame.h', 'clutter-gesture-action.h', 'clutter-grid-layout.h', 'clutter-image.h', @@ -125,6 +126,7 @@ clutter_sources = [ 'clutter-flatten-effect.c', 'clutter-flow-layout.c', 'clutter-frame-clock.c', + 'clutter-frame.c', 'clutter-gesture-action.c', 'clutter-graphene.c', 'clutter-grid-layout.c', @@ -194,6 +196,7 @@ clutter_private_headers = [ 'clutter-effect-private.h', 'clutter-event-private.h', 'clutter-flatten-effect.h', + 'clutter-frame-private.h', 'clutter-graphene.h', 'clutter-gesture-action-private.h', 'clutter-id-pool.h', diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index 00c868c42..2a29f9312 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -107,12 +107,16 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window) static void meta_stage_native_finish_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view) + ClutterStageView *stage_view, + ClutterFrame *frame) { MetaBackend *backend = meta_get_backend (); MetaRenderer *renderer = meta_backend_get_renderer (backend); 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 diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c index 6dfd7cb2f..4f3f5b796 100644 --- a/src/backends/x11/nested/meta-stage-x11-nested.c +++ b/src/backends/x11/nested/meta-stage-x11-nested.c @@ -159,7 +159,8 @@ draw_view (MetaStageX11Nested *stage_nested, static void 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); 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); 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