Skip to content

Commit

Permalink
Weston Performance Fix
Browse files Browse the repository at this point in the history
This fixes the issue where Weston wasn't presenting at the rate
it was expected to. In particular, the RDP backend would always
take 16ms to complete a frame after being sent to the host. Upon
frame completion, Weston would calculat the next frame to present
based on the monitor refresh and target 9ms ahead of that. At 64hz
this ended up having Weston compositor wait for 9ms for the next
frame and that 9ms would add up to the RDP monitor 16ms simulated
VSYNC, resulting in an effective presentation rate of 1/25ms = 40fps.

The VSYNC emulation is now improved and the RDP backend keeps the
frame completion within the total expected refresh, so at 64hz
the frame are kept a total of 16ms apart.

Also updated the VSYNC emulation code to adapt the RDP monitor
refresh to what is specified through the environment variable
WESTON_RDP_MONITOR_REFRESH_RATE.
  • Loading branch information
spronovo committed May 3, 2021
1 parent 01a9381 commit 740ec45
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 25 deletions.
50 changes: 30 additions & 20 deletions libweston/backend-rdp/rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,21 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage,
struct rdp_peers_item *outputPeer;
struct rdp_backend *b = to_rdp_backend(ec);

/* Calculate the time we should complete this frame such that frames
are spaced out by the specified monitor refresh. */
struct timespec now;
weston_compositor_read_presentation_clock(ec, &now);

struct timespec target;
int refresh_nsec = millihz_to_nsec(output_base->current_mode->refresh);
int refresh_msec = refresh_nsec / 1000000;
timespec_add_nsec(&target, &output_base->frame_time, refresh_nsec);

int next_frame_delta = (int)timespec_sub_to_msec(&target, &now);
if ( next_frame_delta < 1 || next_frame_delta > refresh_msec) {
next_frame_delta = refresh_msec;
}

if (b->rdp_peer &&
b->rdp_peer->settings->HiDefRemoteApp) {
/* RAIL mode, repaint RAIL window */
Expand Down Expand Up @@ -324,7 +339,7 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage,
&ec->primary_plane.damage, damage);
}

wl_event_source_timer_update(output->finish_frame_timer, b->rdp_repaint_delay_ms);
wl_event_source_timer_update(output->finish_frame_timer, next_frame_delta);
return 0;
}

Expand Down Expand Up @@ -454,7 +469,7 @@ rdp_output_get_config(struct weston_output *base,
struct rdp_head *h = to_rdp_head(head);

rdp_debug(rdpBackend, "get_config: attached head [%d]: make:%s, mode:%s, name:%s, (%p)\n",
h->index, head->make, head->model, head->name, head);
h->index, head->make, head->model, head->name, head);
rdp_debug(rdpBackend, "get_config: attached head [%d]: x:%d, y:%d, width:%d, height:%d\n",
h->index, h->monitorMode.monitorDef.x, h->monitorMode.monitorDef.y,
h->monitorMode.monitorDef.width, h->monitorMode.monitorDef.height);
Expand Down Expand Up @@ -494,7 +509,7 @@ rdp_output_set_size(struct weston_output *base,
weston_head_set_monitor_strings(head, "weston", "rdp", NULL);

rdp_debug(rdpBackend, "set_size: attached head [%d]: make:%s, mode:%s, name:%s, (%p)\n",
h->index, head->make, head->model, head->name, head);
h->index, head->make, head->model, head->name, head);
rdp_debug(rdpBackend, "set_size: attached head [%d]: x:%d, y:%d, width:%d, height:%d\n",
h->index, h->monitorMode.monitorDef.x, h->monitorMode.monitorDef.y,
h->monitorMode.monitorDef.width, h->monitorMode.monitorDef.height);
Expand Down Expand Up @@ -710,7 +725,7 @@ rdp_head_create(struct weston_compositor *compositor, BOOL isPrimary, struct rdp
monitorMode->rectWeston.width, monitorMode->rectWeston.height);
} else {
head->monitorMode.scale = 1.0f;
head->monitorMode.clientScale = 1;
head->monitorMode.clientScale = 1;
pixman_region32_init(&head->regionClient);
pixman_region32_init(&head->regionWeston);
}
Expand Down Expand Up @@ -1461,7 +1476,7 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
/* Per RDP spec, the x,y position is valid on all input mouse messages,
* except for PTR_FLAGS_WHEEL and PTR_FLAGS_HWHEEL event. Take the opportunity
* to resample our x,y position even when PTR_FLAGS_MOVE isn't explicitly set,
* for example a button down/up only notification, to ensure proper sync with
* for example a button down/up only notification, to ensure proper sync with
* the RDP client.
*/
if (!(flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))) {
Expand Down Expand Up @@ -1752,11 +1767,11 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
settings->NSCodec = TRUE;
settings->FrameMarkerCommandEnabled = TRUE;
settings->SurfaceFrameMarkerEnabled = TRUE;
settings->RemoteApplicationMode = TRUE;
settings->RemoteApplicationMode = TRUE;
settings->RemoteApplicationSupportLevel =
RAIL_LEVEL_SUPPORTED |
RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED |
RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
settings->SupportGraphicsPipeline = TRUE;
Expand Down Expand Up @@ -1887,7 +1902,7 @@ rdp_generate_session_tls(struct rdp_backend *b)
b->server_key_content = (char *)calloc(mem->length+1, 1);
memcpy(b->server_key_content, mem->data, mem->length);
BIO_free_all(bio);

x509 = X509_new();
X509_set_version(x509, 2);
RAND_bytes((unsigned char *)&serial, sizeof(serial));
Expand Down Expand Up @@ -2051,24 +2066,19 @@ rdp_backend_create(struct weston_compositor *compositor,
weston_log("RDP backend: WESTON_RDP_DEBUG_LEVEL: %d\n", b->debugLevel);
/* After here, rdp_debug() is ready to be used */

s = getenv("WESTON_RDP_MONITOR_REFRESH_RATE");
s = getenv("WESTON_RDP_MONITOR_REFRESH_RATE");
if (s) {
if (!safe_strtoint(s, &b->rdp_monitor_refresh_rate))
if (!safe_strtoint(s, &b->rdp_monitor_refresh_rate) ||
b->rdp_monitor_refresh_rate == 0) {
b->rdp_monitor_refresh_rate = RDP_MODE_FREQ;
} else {
b->rdp_monitor_refresh_rate *= 1000;
}
} else {
b->rdp_monitor_refresh_rate = RDP_MODE_FREQ;
}
rdp_debug(b, "RDP backend: WESTON_RDP_MONITOR_REFRESH_RATE: %d\n", b->rdp_monitor_refresh_rate);

s = getenv("WESTON_RDP_REPAINT_DELAY_MS");
if (s) {
if (!safe_strtoint(s, &b->rdp_repaint_delay_ms))
b->rdp_repaint_delay_ms = 16;
} else {
b->rdp_repaint_delay_ms = 16;
}
rdp_debug(b, "RDP backend: WESTON_RDP_REPAINT_DELAY_MS: %d\n", b->rdp_repaint_delay_ms);

clock_getres(CLOCK_MONOTONIC, &ts);
rdp_debug(b, "RDP backend: timer resolution tv_sec:%ld tv_nsec:%ld\n", (intmax_t)ts.tv_sec, ts.tv_nsec);

Expand All @@ -2083,7 +2093,7 @@ rdp_backend_create(struct weston_compositor *compositor,
compositor->backend = &b->base;

fd = use_vsock_fd(config->port);
/* if we are using VSOCK to connect to the rdp backend, we don't need to enforce the TLS
/* if we are using VSOCK to connect to the rdp backend, we don't need to enforce the TLS
encryption, since FreeRDP will consider AF_UNIX and AF_VSOCK as a local connection */
if (fd <= 0 || config->env_socket)
{
Expand Down
9 changes: 4 additions & 5 deletions libweston/backend-rdp/rdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ struct rdp_backend {
uint32_t debug_desktop_scaling_factor; /* must be between 100 to 500 */

int rdp_monitor_refresh_rate;
int rdp_repaint_delay_ms;

#if defined(HAVE_FREERDP_RDPAPPLIST_H) || defined(HAVE_FREERDP_GFXREDIR_H)
void *libFreeRDPServer;
Expand Down Expand Up @@ -222,7 +221,7 @@ struct rdp_peers_item {

struct rdp_monitor_mode {
rdpMonitor monitorDef; // in client coordinate.
int scale; // per monitor DPI scaling.
int scale; // per monitor DPI scaling.
float clientScale;
pixman_rectangle32_t rectWeston; // in weston coordinate.
};
Expand All @@ -247,7 +246,7 @@ struct rdp_output {
uint32_t index;

struct wl_list peers;
struct wl_list link; // rdp_backend::output_list
struct wl_list link; // rdp_backend::output_list
};

typedef struct _rdp_audio_block_info {
Expand Down Expand Up @@ -527,7 +526,7 @@ to_weston_x(RdpPeerContext *peer, int32_t x)
}

/* TO BE REMOVED */
static inline int32_t
static inline int32_t
to_weston_y(RdpPeerContext *peer, int32_t y)
{
return y - peer->regionClientHeads.extents.y1;
Expand Down Expand Up @@ -616,7 +615,7 @@ to_client_coordinate(RdpPeerContext *peerContext, struct weston_output *output,
to_client_scale_only(peerContext, output, scale, &sx, &sy);
if (width && height)
to_client_scale_only(peerContext, output, scale, width, height);
/* translate x/y to offset from this output on client space. */
/* translate x/y to offset from this output on client space. */
sx += head->monitorMode.monitorDef.x;
sy += head->monitorMode.monitorDef.y;
rdp_debug_verbose(b, "%s: (x:%d, y:%d) -> (sx:%d, sy:%d) at head:%s\n",
Expand Down

0 comments on commit 740ec45

Please sign in to comment.