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:
Jonas Ådahl 2020-10-09 18:16:16 +02:00 committed by Marge Bot
parent 9c500f23e4
commit 72b35e07c0
12 changed files with 159 additions and 21 deletions

View 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 */

View 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;
}

View 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 */

View File

@ -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 = {

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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',

View File

@ -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

View File

@ -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