c24a666def
Add post-3.14.2 release fixes from upstream git (as of 2014-12-03), seems to me that they fix important issues leading to crashes (except the black login widnow patch which is cosmetic); previous sr would have removed my branch package if accepted, which we don't want for the sake of sr#263919. Sorry abt that. OBS-URL: https://build.opensuse.org/request/show/263924 OBS-URL: https://build.opensuse.org/package/show/GNOME:Factory/mutter?expand=0&rev=161
227 lines
7.5 KiB
Diff
227 lines
7.5 KiB
Diff
From 7d3204b1965fd54f28f73013f4700caf37dd8216 Mon Sep 17 00:00:00 2001
|
|
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
Date: Fri, 17 Oct 2014 08:49:54 -0400
|
|
Subject: Fix problems resulting in left-over queued frames
|
|
|
|
* Use -1 rather than 0 as a flag for pending queue entries; 0 is
|
|
a valid frame_counter value from Cogl.
|
|
* Consistently handle the fact we can have more than one pending
|
|
entry. It's app misbehavior to submit a new frame before
|
|
_NET_WM_FRAME_DRAWN is received; but we accept such frame messages,
|
|
so we can't just leak them.
|
|
* If we remove send_frame_message_timer, assign the current frame counter
|
|
to pending entries.
|
|
* To try to avoid regressing on this, when sending _NET_WM_FRAME_TIMINGS
|
|
messages, if we have stale messages, or messages with no frame drawn
|
|
time, warn and remove them from the queue rather than just accumulating.
|
|
* Improve commenting.
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=738686
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index eb21c46..254a1a9 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -100,7 +100,7 @@ struct _MetaWindowActorPrivate
|
|
guint disposed : 1;
|
|
|
|
/* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN
|
|
- * client message using the most recent frame in ->frames */
|
|
+ * client message for one or more messages in ->frames */
|
|
guint needs_frame_drawn : 1;
|
|
guint repaint_scheduled : 1;
|
|
|
|
@@ -118,10 +118,21 @@ struct _MetaWindowActorPrivate
|
|
|
|
typedef struct _FrameData FrameData;
|
|
|
|
+/* Each time the application updates the sync request counter to a new even value
|
|
+ * value, we queue a frame into the windows list of frames. Once we're painting
|
|
+ * an update "in response" to the window, we fill in frame_counter with the
|
|
+ * Cogl counter for that frame, and send _NET_WM_FRAME_DRAWN at the end of the
|
|
+ * frame. _NET_WM_FRAME_TIMINGS is sent when we get a frame_complete callback.
|
|
+ *
|
|
+ * As an exception, if a window is completely obscured, we try to throttle drawning
|
|
+ * to a slower frame rate. In this case, frame_counter stays -1 until
|
|
+ * send_frame_message_timeout() runs, at which point we send both the
|
|
+ * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages.
|
|
+ */
|
|
struct _FrameData
|
|
{
|
|
- int64_t frame_counter;
|
|
guint64 sync_request_serial;
|
|
+ int64_t frame_counter;
|
|
gint64 frame_drawn_time;
|
|
};
|
|
|
|
@@ -656,6 +667,30 @@ clip_shadow_under_window (MetaWindowActor *self)
|
|
}
|
|
|
|
static void
|
|
+assign_frame_counter_to_frames (MetaWindowActor *self)
|
|
+{
|
|
+ MetaWindowActorPrivate *priv = self->priv;
|
|
+ GList *l;
|
|
+
|
|
+ /* If the window is obscured, then we're expecting to deal with sending
|
|
+ * frame messages in a timeout, rather than in this paint cycle.
|
|
+ */
|
|
+ if (priv->send_frame_messages_timer != 0)
|
|
+ return;
|
|
+
|
|
+ for (l = priv->frames; l; l = l->next)
|
|
+ {
|
|
+ FrameData *frame = l->data;
|
|
+
|
|
+ if (frame->frame_counter == -1)
|
|
+ {
|
|
+ CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
|
+ frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
meta_window_actor_paint (ClutterActor *actor)
|
|
{
|
|
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
|
|
@@ -671,6 +706,8 @@ meta_window_actor_paint (ClutterActor *actor)
|
|
{
|
|
g_source_remove (priv->send_frame_messages_timer);
|
|
priv->send_frame_messages_timer = 0;
|
|
+
|
|
+ assign_frame_counter_to_frames (self);
|
|
}
|
|
|
|
if (shadow != NULL)
|
|
@@ -873,16 +910,27 @@ send_frame_messages_timeout (gpointer data)
|
|
{
|
|
MetaWindowActor *self = (MetaWindowActor *) data;
|
|
MetaWindowActorPrivate *priv = self->priv;
|
|
- FrameData *frame = g_slice_new0 (FrameData);
|
|
+ GList *l;
|
|
|
|
- frame->sync_request_serial = priv->window->sync_request_serial;
|
|
+ for (l = priv->frames; l;)
|
|
+ {
|
|
+ GList *l_next = l->next;
|
|
+ FrameData *frame = l->data;
|
|
|
|
- do_send_frame_drawn (self, frame);
|
|
- do_send_frame_timings (self, frame, 0, 0);
|
|
+ if (frame->frame_counter == -1)
|
|
+ {
|
|
+ do_send_frame_drawn (self, frame);
|
|
+ do_send_frame_timings (self, frame, 0, 0);
|
|
+
|
|
+ priv->frames = g_list_delete_link (priv->frames, l);
|
|
+ frame_data_free (frame);
|
|
+ }
|
|
+
|
|
+ l = l_next;
|
|
+ }
|
|
|
|
priv->needs_frame_drawn = FALSE;
|
|
priv->send_frame_messages_timer = 0;
|
|
- frame_data_free (frame);
|
|
|
|
return FALSE;
|
|
}
|
|
@@ -933,6 +981,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
|
return;
|
|
|
|
frame = g_slice_new0 (FrameData);
|
|
+ frame->frame_counter = -1;
|
|
|
|
priv->needs_frame_drawn = TRUE;
|
|
|
|
@@ -1905,24 +1954,12 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
|
|
void
|
|
meta_window_actor_pre_paint (MetaWindowActor *self)
|
|
{
|
|
- MetaWindowActorPrivate *priv = self->priv;
|
|
- GList *l;
|
|
-
|
|
if (meta_window_actor_is_destroyed (self))
|
|
return;
|
|
|
|
meta_window_actor_handle_updates (self);
|
|
|
|
- for (l = priv->frames; l != NULL; l = l->next)
|
|
- {
|
|
- FrameData *frame = l->data;
|
|
-
|
|
- if (frame->frame_counter == 0)
|
|
- {
|
|
- CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
|
- frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
|
- }
|
|
- }
|
|
+ assign_frame_counter_to_frames (self);
|
|
}
|
|
|
|
static void
|
|
@@ -1963,16 +2000,23 @@ meta_window_actor_post_paint (MetaWindowActor *self)
|
|
if (meta_window_actor_is_destroyed (self))
|
|
return;
|
|
|
|
- /* This window had damage, but wasn't actually redrawn because
|
|
- * it is obscured. So we should wait until timer expiration
|
|
- * before sending _NET_WM_FRAME_* messages.
|
|
- */
|
|
- if (priv->send_frame_messages_timer != 0)
|
|
- return;
|
|
-
|
|
- if (priv->needs_frame_drawn)
|
|
+ /* If the window had damage, but wasn't actually redrawn because
|
|
+ * it is obscured, we should wait until timer expiration before
|
|
+ * sending _NET_WM_FRAME_* messages.
|
|
+ */
|
|
+ if (priv->send_frame_messages_timer == 0 &&
|
|
+ priv->needs_frame_drawn)
|
|
{
|
|
- do_send_frame_drawn (self, priv->frames->data);
|
|
+ GList *l;
|
|
+
|
|
+ for (l = priv->frames; l; l = l->next)
|
|
+ {
|
|
+ FrameData *frame = l->data;
|
|
+
|
|
+ if (frame->frame_drawn_time == 0)
|
|
+ do_send_frame_drawn (self, frame);
|
|
+ }
|
|
+
|
|
priv->needs_frame_drawn = FALSE;
|
|
}
|
|
|
|
@@ -2057,15 +2101,20 @@ meta_window_actor_frame_complete (MetaWindowActor *self,
|
|
{
|
|
GList *l_next = l->next;
|
|
FrameData *frame = l->data;
|
|
+ gint64 frame_counter = cogl_frame_info_get_frame_counter (frame_info);
|
|
|
|
- if (frame->frame_counter == cogl_frame_info_get_frame_counter (frame_info))
|
|
+ if (frame->frame_counter != -1 && frame->frame_counter <= frame_counter)
|
|
{
|
|
- if (frame->frame_drawn_time != 0)
|
|
- {
|
|
- priv->frames = g_list_delete_link (priv->frames, l);
|
|
- send_frame_timings (self, frame, frame_info, presentation_time);
|
|
- frame_data_free (frame);
|
|
- }
|
|
+ if (G_UNLIKELY (frame->frame_drawn_time == 0))
|
|
+ g_warning ("%s: Frame has assigned frame counter but no frame drawn time",
|
|
+ priv->window->desc);
|
|
+ if (G_UNLIKELY (frame->frame_counter < frame_counter))
|
|
+ g_warning ("%s: frame_complete callback never occurred for frame %" G_GINT64_FORMAT,
|
|
+ priv->window->desc, frame->frame_counter);
|
|
+
|
|
+ priv->frames = g_list_delete_link (priv->frames, l);
|
|
+ send_frame_timings (self, frame, frame_info, presentation_time);
|
|
+ frame_data_free (frame);
|
|
}
|
|
|
|
l = l_next;
|
|
--
|
|
cgit v0.10.1
|