nvnc_fb: Add a mechanism for signaling that a frame is in use

pull/30/head
Andri Yngvason 2020-04-04 12:33:18 +00:00
parent 8c27878dd1
commit f45f90ed9b
4 changed files with 28 additions and 4 deletions

View File

@ -2,10 +2,12 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdatomic.h>
struct nvnc_fb { struct nvnc_fb {
int ref; int ref;
void* addr; void* addr;
atomic_bool is_locked;
size_t size; size_t size;
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;

View File

@ -73,6 +73,9 @@ struct nvnc_fb* nvnc_fb_new(uint16_t width, uint16_t height,
void nvnc_fb_ref(struct nvnc_fb* fb); void nvnc_fb_ref(struct nvnc_fb* fb);
void nvnc_fb_unref(struct nvnc_fb* fb); void nvnc_fb_unref(struct nvnc_fb* fb);
bool nvnc_fb_lock(struct nvnc_fb*);
void nvnc_fb_unlock(struct nvnc_fb*);
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

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/param.h> #include <sys/param.h>
#include <stdatomic.h>
#define UDIV_UP(a, b) (((a) + (b) - 1) / (b)) #define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
#define ALIGN_UP(n, a) (UDIV_UP(n, a) * a) #define ALIGN_UP(n, a) (UDIV_UP(n, a) * a)
@ -39,6 +40,19 @@ struct nvnc_fb* nvnc_fb_new(uint16_t width, uint16_t height,
return fb; return fb;
} }
EXPORT
bool nvnc_fb_lock(struct nvnc_fb* fb)
{
bool expected = false;
return atomic_compare_exchange_strong(&fb->is_locked, &expected, true);
}
EXPORT
void nvnc_fb_unlock(struct nvnc_fb* fb)
{
fb->is_locked = false;
}
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,9 +474,13 @@ 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))
return;
client->is_updating = true; client->is_updating = true;
schedule_client_update_fb(client); if (schedule_client_update_fb(client) < 0)
nvnc_fb_unlock(client->server->frame);
} }
static int on_client_fb_update_request(struct nvnc_client* client) static int on_client_fb_update_request(struct nvnc_client* client)
@ -855,7 +859,7 @@ void do_client_update_fb(void* work)
{ {
struct fb_update_work* update = aml_get_userdata(work); struct fb_update_work* update = aml_get_userdata(work);
struct nvnc_client* client = update->client; struct nvnc_client* client = update->client;
const struct nvnc_fb* fb = update->fb; struct nvnc_fb* fb = update->fb;
enum rfb_encodings encoding = choose_frame_encoding(client); enum rfb_encodings encoding = choose_frame_encoding(client);
if (encoding == -1) { if (encoding == -1) {
@ -896,8 +900,10 @@ void on_client_update_fb_done(void* work)
struct nvnc_client* client = update->client; struct nvnc_client* client = update->client;
struct vec* frame = &update->frame; struct vec* frame = &update->frame;
client_ref(client); nvnc_fb_unlock(update->fb);
nvnc_fb_unref(update->fb);
client_ref(client);
if (client->net_stream->state != STREAM_STATE_CLOSED) { if (client->net_stream->state != STREAM_STATE_CLOSED) {
struct rcbuf* payload = rcbuf_new(frame->data, frame->len); struct rcbuf* payload = rcbuf_new(frame->data, frame->len);
@ -913,7 +919,6 @@ void on_client_update_fb_done(void* work)
client->n_pending_requests--; client->n_pending_requests--;
process_fb_update_requests(client); process_fb_update_requests(client);
nvnc_fb_unref(update->fb);
DTRACE_PROBE1(neatvnc, update_fb_done, client); DTRACE_PROBE1(neatvnc, update_fb_done, client);