From cfb76fedb641a58d41efa01edf20ca480029030a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 23 Nov 2017 10:22:23 +0100 Subject: [PATCH] broadway: Roundtrip each update to rate limit redraw --- gdk/broadway/broadway-output.c | 10 +++ gdk/broadway/broadway-output.h | 3 + gdk/broadway/broadway-protocol.h | 20 +++++- gdk/broadway/broadway-server.c | 100 ++++++++++++++++++++++++++++- gdk/broadway/broadway-server.h | 3 + gdk/broadway/broadway.js | 11 ++++ gdk/broadway/broadwayd.c | 7 ++ gdk/broadway/gdkbroadway-server.c | 16 ++++- gdk/broadway/gdkbroadway-server.h | 3 + gdk/broadway/gdkeventsource.c | 7 ++ gdk/broadway/gdkprivate-broadway.h | 5 +- gdk/broadway/gdkwindow-broadway.c | 46 +++++++++---- 12 files changed, 211 insertions(+), 20 deletions(-) diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c index 193d68e3b3..036f71b0fa 100644 --- a/gdk/broadway/broadway-output.c +++ b/gdk/broadway/broadway-output.c @@ -237,6 +237,16 @@ broadway_output_destroy_surface(BroadwayOutput *output, int id) append_uint16 (output, id); } +void +broadway_output_roundtrip (BroadwayOutput *output, + int id, + guint32 tag) +{ + write_header (output, BROADWAY_OP_ROUNDTRIP); + append_uint16 (output, id); + append_uint32 (output, tag); +} + void broadway_output_set_show_keyboard (BroadwayOutput *output, gboolean show) diff --git a/gdk/broadway/broadway-output.h b/gdk/broadway/broadway-output.h index 024df8e1ca..bf35be2aec 100644 --- a/gdk/broadway/broadway-output.h +++ b/gdk/broadway/broadway-output.h @@ -42,6 +42,9 @@ void broadway_output_lower_surface (BroadwayOutput *output, int id); void broadway_output_destroy_surface (BroadwayOutput *output, int id); +void broadway_output_roundtrip (BroadwayOutput *output, + int id, + guint32 tag); void broadway_output_move_resize_surface (BroadwayOutput *output, int id, gboolean has_pos, diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h index 7e8a37c59e..41861ef3f1 100644 --- a/gdk/broadway/broadway-protocol.h +++ b/gdk/broadway/broadway-protocol.h @@ -37,7 +37,8 @@ typedef enum { BROADWAY_EVENT_CONFIGURE_NOTIFY = 'w', BROADWAY_EVENT_DELETE_NOTIFY = 'W', BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 'd', - BROADWAY_EVENT_FOCUS = 'f' + BROADWAY_EVENT_FOCUS = 'f', + BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 'F', } BroadwayEventType; typedef enum { @@ -60,6 +61,7 @@ typedef enum { BROADWAY_OP_UPLOAD_TEXTURE = 't', BROADWAY_OP_RELEASE_TEXTURE = 'T', BROADWAY_OP_SET_NODES = 'n', + BROADWAY_OP_ROUNDTRIP = 'F', } BroadwayOpType; typedef struct { @@ -128,6 +130,13 @@ typedef struct { gint32 height; } BroadwayInputConfigureNotify; +typedef struct { + BroadwayInputBaseMsg base; + gint32 id; + guint32 tag; + guint32 local; +} BroadwayInputRoundtripNotify; + typedef struct { BroadwayInputBaseMsg base; guint32 width; @@ -155,6 +164,7 @@ typedef union { BroadwayInputKeyMsg key; BroadwayInputGrabReply grab_reply; BroadwayInputConfigureNotify configure_notify; + BroadwayInputRoundtripNotify roundtrip_notify; BroadwayInputDeleteNotify delete_notify; BroadwayInputScreenResizeNotify screen_resize_notify; BroadwayInputFocusMsg focus; @@ -177,6 +187,7 @@ typedef enum { BROADWAY_REQUEST_UPLOAD_TEXTURE, BROADWAY_REQUEST_RELEASE_TEXTURE, BROADWAY_REQUEST_SET_NODES, + BROADWAY_REQUEST_ROUNDTRIP, } BroadwayRequestType; typedef struct { @@ -190,6 +201,12 @@ typedef struct { guint32 id; } BroadwayRequestDestroyWindow, BroadwayRequestShowWindow, BroadwayRequestHideWindow, BroadwayRequestFocusWindow; +typedef struct { + BroadwayRequestBase base; + guint32 id; + guint32 tag; +} BroadwayRequestRoundtrip; + typedef struct { BroadwayRequestBase base; guint32 id; @@ -257,6 +274,7 @@ typedef union { BroadwayRequestNewWindow new_window; BroadwayRequestFlush flush; BroadwayRequestSync sync; + BroadwayRequestRoundtrip roundtrip; BroadwayRequestQueryMouse query_mouse; BroadwayRequestDestroyWindow destroy_window; BroadwayRequestShowWindow show_window; diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index 859fa68c41..3f9dfebc16 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -35,6 +35,12 @@ #include #endif + +typedef struct { + int id; + guint32 tag; +} BroadwayOutstandingRoundtrip; + typedef struct BroadwayInput BroadwayInput; typedef struct BroadwayWindow BroadwayWindow; struct _BroadwayServer { @@ -81,6 +87,8 @@ struct _BroadwayServer { int future_root_y; guint32 future_state; int future_mouse_in_toplevel; + + GList *outstanding_roundtrips; }; struct _BroadwayServerClass @@ -122,6 +130,7 @@ struct BroadwayWindow { }; static void broadway_server_resync_windows (BroadwayServer *server); +static void send_outstanding_roundtrips (BroadwayServer *server); static GType broadway_server_get_type (void); @@ -288,6 +297,8 @@ update_event_state (BroadwayServer *server, window->y = message->configure_notify.y; } break; + case BROADWAY_EVENT_ROUNDTRIP_NOTIFY: + break; case BROADWAY_EVENT_DELETE_NOTIFY: break; case BROADWAY_EVENT_SCREEN_SIZE_CHANGED: @@ -429,6 +440,12 @@ update_future_pointer_info (BroadwayServer *server, BroadwayInputPointerMsg *dat server->future_mouse_in_toplevel = data->mouse_window_id; } +static void +queue_input_message (BroadwayServer *server, BroadwayInputMsg *msg) +{ + server->input_messages = g_list_append (server->input_messages, g_memdup (msg, sizeof (BroadwayInputMsg))); +} + static void parse_input_message (BroadwayInput *input, const unsigned char *message) { @@ -436,6 +453,7 @@ parse_input_message (BroadwayInput *input, const unsigned char *message) BroadwayInputMsg msg; guint32 *p; gint64 time_; + GList *l; memset (&msg, 0, sizeof (msg)); @@ -512,6 +530,26 @@ parse_input_message (BroadwayInput *input, const unsigned char *message) msg.configure_notify.height = ntohl (*p++); break; + case BROADWAY_EVENT_ROUNDTRIP_NOTIFY: + msg.roundtrip_notify.id = ntohl (*p++); + msg.roundtrip_notify.tag = ntohl (*p++); + msg.roundtrip_notify.local = FALSE; + + /* Remove matched outstanding roundtrips */ + for (l = server->outstanding_roundtrips; l != NULL; l = l->next) + { + BroadwayOutstandingRoundtrip *rt = l->data; + + if (rt->id == msg.roundtrip_notify.id && + rt->tag == msg.roundtrip_notify.tag) + { + server->outstanding_roundtrips = g_list_delete_link (server->outstanding_roundtrips, l); + g_free (rt); + break; + } + } + break; + case BROADWAY_EVENT_DELETE_NOTIFY: msg.delete_notify.id = ntohl (*p++); break; @@ -526,8 +564,7 @@ parse_input_message (BroadwayInput *input, const unsigned char *message) break; } - server->input_messages = g_list_append (server->input_messages, g_memdup (&msg, sizeof (msg))); - + queue_input_message (server, &msg); } static inline void @@ -697,7 +734,11 @@ broadway_server_read_all_input_nonblocking (BroadwayInput *input) } if (input->server->input == input) - input->server->input = NULL; + { + send_outstanding_roundtrips (input->server); + + input->server->input = NULL; + } broadway_input_free (input); if (res < 0) { @@ -758,6 +799,23 @@ broadway_server_get_screen_size (BroadwayServer *server, *height = server->root->height; } +static void +broadway_server_fake_roundtrip_reply (BroadwayServer *server, + gint id, + guint32 tag) +{ + BroadwayInputMsg msg; + + msg.base.type = BROADWAY_EVENT_ROUNDTRIP_NOTIFY; + msg.base.serial = 0; + msg.base.time = server->last_seen_time; + msg.roundtrip_notify.id = id; + msg.roundtrip_notify.tag = tag; + msg.roundtrip_notify.local = 1; + + queue_input_message (server, &msg); + queue_process_input_at_idle (server); +} void broadway_server_flush (BroadwayServer *server) @@ -768,9 +826,28 @@ broadway_server_flush (BroadwayServer *server) server->saved_serial = broadway_output_get_next_serial (server->output); broadway_output_free (server->output); server->output = NULL; + send_outstanding_roundtrips (server); } } +void +broadway_server_roundtrip (BroadwayServer *server, + gint id, + guint32 tag) +{ + if (server->output) + { + BroadwayOutstandingRoundtrip *rt = g_new0 (BroadwayOutstandingRoundtrip, 1); + rt->id = id; + rt->tag = tag; + server->outstanding_roundtrips = g_list_prepend (server->outstanding_roundtrips, rt); + + broadway_output_roundtrip (server->output, id, tag); + } + else + broadway_server_fake_roundtrip_reply (server, id, tag); +} + #if 0 /* TODO: This is not used atm, is it needed? */ /* Note: This may be called while handling a message (i.e. sorta recursively) */ @@ -1000,6 +1077,21 @@ start_input (HttpRequest *request) g_strfreev (lines); } +static void +send_outstanding_roundtrips (BroadwayServer *server) +{ + GList *l; + + for (l = server->outstanding_roundtrips; l != NULL; l = l->next) + { + BroadwayOutstandingRoundtrip *rt = l->data; + broadway_server_fake_roundtrip_reply (server, rt->id, rt->tag); + } + + g_list_free_full (server->outstanding_roundtrips, g_free); + server->outstanding_roundtrips = NULL; +} + static void start (BroadwayInput *input) { @@ -1011,12 +1103,14 @@ start (BroadwayInput *input) if (server->output) { + send_outstanding_roundtrips (server); broadway_output_disconnected (server->output); broadway_output_flush (server->output); } if (server->input != NULL) { + send_outstanding_roundtrips (server); broadway_input_free (server->input); server->input = NULL; } diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h index 4bc81a70d2..d120261181 100644 --- a/gdk/broadway/broadway-server.h +++ b/gdk/broadway/broadway-server.h @@ -29,6 +29,9 @@ BroadwayServer *broadway_server_on_unix_socket_new (char * gboolean broadway_server_has_client (BroadwayServer *server); void broadway_server_flush (BroadwayServer *server); void broadway_server_sync (BroadwayServer *server); +void broadway_server_roundtrip (BroadwayServer *server, + gint id, + guint32 tag); void broadway_server_get_screen_size (BroadwayServer *server, guint32 *width, guint32 *height); diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js index 9f9ca2357f..acbd80d236 100644 --- a/gdk/broadway/broadway.js +++ b/gdk/broadway/broadway.js @@ -245,6 +245,11 @@ function cmdDeleteSurface(id) delete surfaces[id]; } +function cmdRoundtrip(id, tag) +{ + sendInput("F", [id, tag]); +} + function cmdMoveResizeSurface(id, has_pos, x, y, has_size, w, h) { var surface = surfaces[id]; @@ -737,6 +742,12 @@ function handleCommands(cmd) cmdDeleteSurface(id); break; + case 'F': // RoundTrip + id = cmd.get_16(); + var tag = cmd.get_32(); + cmdRoundtrip(id, tag); + break; + case 'm': // Move a surface id = cmd.get_16(); var ops = cmd.get_flags(); diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index 50d71f521d..638b7f9b16 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -325,6 +325,11 @@ client_handle_request (BroadwayClient *client, send_reply (client, request, (BroadwayReply *)&reply_sync, sizeof (reply_sync), BROADWAY_REPLY_SYNC); break; + case BROADWAY_REQUEST_ROUNDTRIP: + broadway_server_roundtrip (server, + request->roundtrip.id, + request->roundtrip.tag); + break; case BROADWAY_REQUEST_QUERY_MOUSE: broadway_server_query_mouse (server, &reply_query_mouse.toplevel, @@ -728,6 +733,8 @@ get_event_size (int type) return sizeof (BroadwayInputGrabReply); case BROADWAY_EVENT_CONFIGURE_NOTIFY: return sizeof (BroadwayInputConfigureNotify); + case BROADWAY_EVENT_ROUNDTRIP_NOTIFY: + return sizeof (BroadwayInputRoundtripNotify); case BROADWAY_EVENT_DELETE_NOTIFY: return sizeof (BroadwayInputDeleteNotify); case BROADWAY_EVENT_SCREEN_SIZE_CHANGED: diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index 28959a764e..fa24e08cd5 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -48,7 +48,6 @@ struct _GdkBroadwayServer { guint process_input_idle; GList *incomming; - }; struct _GdkBroadwayServerClass @@ -422,7 +421,7 @@ _gdk_broadway_server_sync (GdkBroadwayServer *server) BroadwayReply *reply; serial = gdk_broadway_server_send_message (server, msg, - BROADWAY_REQUEST_SYNC); + BROADWAY_REQUEST_SYNC); reply = gdk_broadway_server_wait_for_reply (server, serial); g_assert (reply->base.type == BROADWAY_REPLY_SYNC); @@ -432,6 +431,19 @@ _gdk_broadway_server_sync (GdkBroadwayServer *server) return; } +void +_gdk_broadway_server_roundtrip (GdkBroadwayServer *server, + gint32 id, + guint32 tag) +{ + BroadwayRequestRoundtrip msg; + + msg.id = id; + msg.tag = tag; + gdk_broadway_server_send_message (server, msg, + BROADWAY_REQUEST_ROUNDTRIP); +} + void _gdk_broadway_server_query_mouse (GdkBroadwayServer *server, guint32 *toplevel, diff --git a/gdk/broadway/gdkbroadway-server.h b/gdk/broadway/gdkbroadway-server.h index 8ff26ebcfb..aec5669959 100644 --- a/gdk/broadway/gdkbroadway-server.h +++ b/gdk/broadway/gdkbroadway-server.h @@ -18,6 +18,9 @@ GdkBroadwayServer *_gdk_broadway_server_new (const char GError **error); void _gdk_broadway_server_flush (GdkBroadwayServer *server); void _gdk_broadway_server_sync (GdkBroadwayServer *server); +void _gdk_broadway_server_roundtrip (GdkBroadwayServer *server, + gint32 id, + guint32 tag); gulong _gdk_broadway_server_get_next_serial (GdkBroadwayServer *server); guint32 _gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server); gboolean _gdk_broadway_server_lookahead_event (GdkBroadwayServer *server, diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c index 0935cc9261..2f51212ca8 100644 --- a/gdk/broadway/gdkeventsource.c +++ b/gdk/broadway/gdkeventsource.c @@ -21,6 +21,7 @@ #include "gdkdevicemanager-broadway.h" #include "gdkinternals.h" +#include "gdkframeclockprivate.h" #include @@ -336,6 +337,12 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message) } break; + case BROADWAY_EVENT_ROUNDTRIP_NOTIFY: + window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->roundtrip_notify.id)); + if (window) + _gdk_broadway_roundtrip_notify (window, message->roundtrip_notify.tag, message->roundtrip_notify.local); + break; + case BROADWAY_EVENT_DELETE_NOTIFY: window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->delete_notify.id)); if (window) diff --git a/gdk/broadway/gdkprivate-broadway.h b/gdk/broadway/gdkprivate-broadway.h index 146ff378e2..3d8faaa241 100644 --- a/gdk/broadway/gdkprivate-broadway.h +++ b/gdk/broadway/gdkprivate-broadway.h @@ -79,8 +79,9 @@ gboolean _gdk_broadway_moveresize_handle_event (GdkDisplay *display, BroadwayInputMsg *msg); gboolean _gdk_broadway_moveresize_configure_done (GdkDisplay *display, GdkWindow *window); - - +void _gdk_broadway_roundtrip_notify (GdkWindow *window, + guint32 tag, + gboolean local_reply); void _gdk_broadway_selection_window_destroyed (GdkWindow *window); void _gdk_broadway_window_grab_check_destroy (GdkWindow *window); void _gdk_broadway_window_grab_check_unmap (GdkWindow *window, diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c index 4b71b45c91..9eb817398a 100644 --- a/gdk/broadway/gdkwindow-broadway.c +++ b/gdk/broadway/gdkwindow-broadway.c @@ -37,6 +37,7 @@ #include "gdkdeviceprivate.h" #include "gdkeventsource.h" #include +#include #include #include @@ -96,17 +97,6 @@ find_broadway_display (void) return display; } -static void -update_dirty_windows_and_sync (void) -{ - GdkBroadwayDisplay *display; - - display = GDK_BROADWAY_DISPLAY (find_broadway_display ()); - g_assert (display != NULL); - - gdk_display_flush (GDK_DISPLAY (display)); -} - static guint flush_id = 0; static gboolean @@ -165,11 +155,43 @@ gdk_window_impl_broadway_finalize (GObject *object) G_OBJECT_CLASS (gdk_window_impl_broadway_parent_class)->finalize (object); } +static gboolean +thaw_clock_cb (GdkFrameClock *clock) +{ + _gdk_frame_clock_thaw (clock); + g_object_unref (clock); + return G_SOURCE_REMOVE; +} + +void +_gdk_broadway_roundtrip_notify (GdkWindow *window, + guint32 tag, + gboolean local_reply) +{ + GdkFrameClock *clock = gdk_window_get_frame_clock (window); + + /* If there is no remove web client, rate limit update to once a second */ + if (local_reply) + g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock)); + else + _gdk_frame_clock_thaw (clock); +} + static void on_frame_clock_after_paint (GdkFrameClock *clock, GdkWindow *window) { - update_dirty_windows_and_sync (); + GdkDisplay *display = gdk_window_get_display (window); + GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl); + GdkBroadwayDisplay *broadway_display; + + _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window)); + + broadway_display = GDK_BROADWAY_DISPLAY (display); + + _gdk_broadway_server_roundtrip (broadway_display->server, impl->id, _gdk_display_get_next_serial (display)); + + gdk_display_flush (display); } static void