[mutter] clutter: Introduce ClutterFrame



commit 72b35e07c027c69048a1211ca987b3a05f0eb79d
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Fri Oct 9 18:16:16 2020 +0200

    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>

 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 +++-
 src/backends/x11/nested/meta-stage-x11-nested.c |  6 +++-
 12 files changed, 159 insertions(+), 21 deletions(-)
---
diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h
new file mode 100644
index 0000000000..e0088564fc
--- /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 <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 */
diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c
new file mode 100644
index 0000000000..3c708da9dc
--- /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 <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;
+}
diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h
new file mode 100644
index 0000000000..d3608e81ca
--- /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 <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 */
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index 2b12b93ed8..81662de061 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 2d3192df08..5f7c489675 100644
--- a/clutter/clutter/clutter-stage-window.c
+++ b/clutter/clutter/clutter-stage-window.c
@@ -3,6 +3,7 @@
 #include <glib-object.h>
 
 #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 0f2d5bc286..b1ebd2badf 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 1453eaaadf..569e36604b 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 d09f8afed4..9b97cfc9e9 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 ffc13bad7c..02b13781a2 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 4b617bd989..9f20d7ba39 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 00c868c422..2a29f93127 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 6dfd7cb2fd..4f3f5b7962 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]