Don't show partial frames to new clients

pull/30/head
Andri Yngvason 2020-04-04 14:00:03 +00:00
parent f45f90ed9b
commit 8fc5c18b28
5 changed files with 40 additions and 3 deletions

View File

@ -70,6 +70,7 @@ struct nvnc_client {
struct pixman_region16 damage; struct pixman_region16 damage;
int n_pending_requests; int n_pending_requests;
bool is_updating; bool is_updating;
bool needs_whole_frame;
nvnc_client_fn cleanup_fn; nvnc_client_fn cleanup_fn;
z_stream z_stream; z_stream z_stream;
struct tight_encoder tight_encoder; struct tight_encoder tight_encoder;

View File

@ -4,10 +4,13 @@
#include <stdint.h> #include <stdint.h>
#include <stdatomic.h> #include <stdatomic.h>
#include "neatvnc.h"
struct nvnc_fb { struct nvnc_fb {
int ref; int ref;
void* addr; void* addr;
atomic_bool is_locked; atomic_bool is_locked;
enum nvnc_fb_flags flags;
size_t size; size_t size;
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;

View File

@ -32,6 +32,10 @@ enum nvnc_button_mask {
NVNC_SCROLL_DOWN = 1 << 4, NVNC_SCROLL_DOWN = 1 << 4,
}; };
enum nvnc_fb_flags {
NVNC_FB_PARTIAL = 1 << 0, // The buffer contains only the damaged region
};
typedef void (*nvnc_key_fn)(struct nvnc_client*, uint32_t keysym, typedef void (*nvnc_key_fn)(struct nvnc_client*, uint32_t keysym,
bool is_pressed); bool is_pressed);
typedef void (*nvnc_pointer_fn)(struct nvnc_client*, uint16_t x, uint16_t y, typedef void (*nvnc_pointer_fn)(struct nvnc_client*, uint16_t x, uint16_t y,
@ -76,6 +80,9 @@ void nvnc_fb_unref(struct nvnc_fb* fb);
bool nvnc_fb_lock(struct nvnc_fb*); bool nvnc_fb_lock(struct nvnc_fb*);
void nvnc_fb_unlock(struct nvnc_fb*); void nvnc_fb_unlock(struct nvnc_fb*);
enum nvnc_fb_flags nvnc_fb_get_flags(const struct nvnc_fb*);
void nvnc_fb_set_flags(struct nvnc_fb*, enum nvnc_fb_flags);
void* nvnc_fb_get_addr(const struct nvnc_fb* fb); void* nvnc_fb_get_addr(const struct nvnc_fb* fb);
uint16_t nvnc_fb_get_width(const struct nvnc_fb* fb); uint16_t nvnc_fb_get_width(const struct nvnc_fb* fb);
uint16_t nvnc_fb_get_height(const struct nvnc_fb* fb); uint16_t nvnc_fb_get_height(const struct nvnc_fb* fb);

View File

@ -53,6 +53,18 @@ void nvnc_fb_unlock(struct nvnc_fb* fb)
fb->is_locked = false; fb->is_locked = false;
} }
EXPORT
enum nvnc_fb_flags nvnc_fb_get_flags(const struct nvnc_fb* fb)
{
return fb->flags;
}
EXPORT
void nvnc_fb_set_flags(struct nvnc_fb* fb, enum nvnc_fb_flags flags)
{
fb->flags = flags;
}
EXPORT EXPORT
void* nvnc_fb_get_addr(const struct nvnc_fb* fb) void* nvnc_fb_get_addr(const struct nvnc_fb* fb)
{ {

View File

@ -474,13 +474,23 @@ static void process_fb_update_requests(struct nvnc_client* client)
if (client->is_updating || client->n_pending_requests == 0) if (client->is_updating || client->n_pending_requests == 0)
return; return;
if (!nvnc_fb_lock(client->server->frame)) struct nvnc_fb* fb = client->server->frame;
if (!nvnc_fb_lock(fb))
return; return;
client->is_updating = true; if (client->needs_whole_frame && (fb->flags & NVNC_FB_PARTIAL))
goto abort;
client->is_updating = true;
if (schedule_client_update_fb(client) < 0) if (schedule_client_update_fb(client) < 0)
nvnc_fb_unlock(client->server->frame); goto abort;
return;
abort:
nvnc_fb_unlock(fb);
client->is_updating = false;
} }
static int on_client_fb_update_request(struct nvnc_client* client) static int on_client_fb_update_request(struct nvnc_client* client)
@ -500,6 +510,9 @@ static int on_client_fb_update_request(struct nvnc_client* client)
int width = ntohs(msg->width); int width = ntohs(msg->width);
int height = ntohs(msg->height); int height = ntohs(msg->height);
if (!incremental)
client->needs_whole_frame = true;
client->n_pending_requests++; client->n_pending_requests++;
/* Note: The region sent from the client is ignored for incremental /* Note: The region sent from the client is ignored for incremental
@ -911,6 +924,7 @@ void on_client_update_fb_done(void* work)
stream_send(client->net_stream, payload, on_write_frame_done, stream_send(client->net_stream, payload, on_write_frame_done,
client); client);
DTRACE_PROBE1(neatvnc, send_fb_done, client); DTRACE_PROBE1(neatvnc, send_fb_done, client);
client->needs_whole_frame = false;
} else { } else {
client->is_updating = false; client->is_updating = false;
vec_destroy(frame); vec_destroy(frame);