Use new NeatVNC buffer submission API
parent
3b6a07a3b6
commit
6c3d9bbb9f
126
src/main.c
126
src/main.c
|
@ -68,6 +68,13 @@
|
|||
|
||||
#define MAYBE_UNUSED __attribute__((unused))
|
||||
|
||||
struct fb_side_data {
|
||||
struct pixman_region16 damage;
|
||||
LIST_ENTRY(fb_side_data) link;
|
||||
};
|
||||
|
||||
LIST_HEAD(fb_side_data_list, fb_side_data);
|
||||
|
||||
struct wayvnc {
|
||||
bool do_exit;
|
||||
|
||||
|
@ -96,22 +103,20 @@ struct wayvnc {
|
|||
|
||||
struct nvnc* nvnc;
|
||||
struct nvnc_display* nvnc_display;
|
||||
struct nvnc_fb* buffer;
|
||||
struct nvnc_fb_pool* fb_pool;
|
||||
struct fb_side_data_list fb_side_data_list;
|
||||
|
||||
struct damage_refinery damage_refinery;
|
||||
struct pixman_region16 current_damage;
|
||||
|
||||
const char* kb_layout;
|
||||
const char* kb_variant;
|
||||
|
||||
uint32_t damage_area_sum;
|
||||
uint32_t n_frames_captured;
|
||||
uint32_t n_frames_rendered;
|
||||
};
|
||||
|
||||
void wayvnc_exit(struct wayvnc* self);
|
||||
void on_capture_done(struct screencopy* sc);
|
||||
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
||||
|
||||
#if defined(GIT_VERSION)
|
||||
static const char wayvnc_version[] = GIT_VERSION;
|
||||
|
@ -506,12 +511,10 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port, bool is_unix
|
|||
|
||||
nvnc_add_display(self->nvnc, self->nvnc_display);
|
||||
|
||||
nvnc_set_userdata(self->nvnc, self);
|
||||
nvnc_set_userdata(self->nvnc, self, NULL);
|
||||
|
||||
nvnc_set_name(self->nvnc, "WayVNC");
|
||||
|
||||
nvnc_display_set_render_fn(self->nvnc_display, on_render);
|
||||
|
||||
if (self->cfg.enable_auth &&
|
||||
nvnc_enable_auth(self->nvnc, self->cfg.private_key_file,
|
||||
self->cfg.certificate_file, on_auth, self) < 0) {
|
||||
|
@ -556,43 +559,43 @@ int wayvnc_start_capture_immediate(struct wayvnc* self)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
|
||||
static void fb_side_data_destroy(void* userdata)
|
||||
{
|
||||
struct nvnc* nvnc = nvnc_display_get_server(display);
|
||||
struct wayvnc* self = nvnc_get_userdata(nvnc);
|
||||
struct fb_side_data* fb_side_data = userdata;
|
||||
LIST_REMOVE(fb_side_data, link);
|
||||
pixman_region_fini(&fb_side_data->damage);
|
||||
free(fb_side_data);
|
||||
}
|
||||
|
||||
if (!self->screencopy.back)
|
||||
return;
|
||||
|
||||
self->n_frames_rendered++;
|
||||
static void wv_damage_all_buffers(struct wayvnc* self,
|
||||
struct pixman_region16* region)
|
||||
{
|
||||
struct fb_side_data *item;
|
||||
LIST_FOREACH(item, &self->fb_side_data_list, link)
|
||||
pixman_region_union(&item->damage, &item->damage, region);
|
||||
}
|
||||
|
||||
void wayvnc_render_to_fb(struct wayvnc* self, struct nvnc_fb* fb)
|
||||
{
|
||||
DTRACE_PROBE(wayvnc, render_start);
|
||||
|
||||
struct fb_side_data* fb_side_data = nvnc_get_userdata(fb);
|
||||
assert(fb_side_data);
|
||||
|
||||
enum wl_output_transform transform = self->selected_output->transform;
|
||||
wv_pixman_render(fb, self->screencopy.back, transform,
|
||||
&self->current_damage);
|
||||
pixman_region_clear(&self->current_damage);
|
||||
&fb_side_data->damage);
|
||||
pixman_region_clear(&fb_side_data->damage);
|
||||
|
||||
DTRACE_PROBE(wayvnc, render_end);
|
||||
}
|
||||
|
||||
static void wayvnc_damage_region(struct wayvnc* self,
|
||||
struct pixman_region16* damage)
|
||||
{
|
||||
pixman_region_union(&self->current_damage, &self->current_damage, damage);
|
||||
nvnc_display_damage_region(self->nvnc_display, damage);
|
||||
}
|
||||
|
||||
// TODO: Handle transform change too
|
||||
void on_output_dimension_change(struct output* output)
|
||||
{
|
||||
struct wayvnc* self = output->userdata;
|
||||
assert(self->selected_output == output);
|
||||
|
||||
// The buffer must have been set as a result of a screencopy frame
|
||||
if (!self->buffer)
|
||||
return;
|
||||
|
||||
log_debug("Output dimensions changed. Restarting frame capturer...\n");
|
||||
|
||||
screencopy_stop(&self->screencopy);
|
||||
|
@ -629,26 +632,34 @@ void wayvnc_process_frame(struct wayvnc* self)
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->buffer && (width != nvnc_fb_get_width(self->buffer) ||
|
||||
height != nvnc_fb_get_height(self->buffer))) {
|
||||
log_debug("Frame dimensions changed. Resizing...\n");
|
||||
|
||||
nvnc_fb_unref(self->buffer);
|
||||
self->buffer = NULL;
|
||||
bool dimensions_changed =
|
||||
nvnc_fb_pool_resize(self->fb_pool, width, height, format);
|
||||
if (dimensions_changed) {
|
||||
damage_refinery_destroy(&self->damage_refinery);
|
||||
}
|
||||
|
||||
// TODO: Maybe the buffer needs to be changed inside on_render?
|
||||
if (!self->buffer) {
|
||||
self->buffer = nvnc_fb_new(width, height, format);
|
||||
nvnc_display_set_buffer(self->nvnc_display, self->buffer);
|
||||
log_debug("Set nvnc buffer: %p\n", self->buffer);
|
||||
|
||||
damage_refinery_init(&self->damage_refinery,
|
||||
self->screencopy.back->width,
|
||||
self->screencopy.back->height);
|
||||
}
|
||||
|
||||
struct nvnc_fb *fb = nvnc_fb_pool_acquire(self->fb_pool);
|
||||
if (!fb) {
|
||||
log_error("Failed to acquire a vnc buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct fb_side_data* fb_side_data = nvnc_get_userdata(fb);
|
||||
if (!fb_side_data) {
|
||||
fb_side_data = calloc(1, sizeof(*fb_side_data));
|
||||
assert(fb_side_data);
|
||||
|
||||
/* This is a new buffer, so the whole surface is damaged. */
|
||||
pixman_region_init_rect(&fb_side_data->damage, 0, 0, width,
|
||||
height);
|
||||
|
||||
nvnc_set_userdata(fb, fb_side_data, fb_side_data_destroy);
|
||||
LIST_INSERT_HEAD(&self->fb_side_data_list, fb_side_data, link);
|
||||
}
|
||||
|
||||
self->n_frames_captured++;
|
||||
self->damage_area_sum +=
|
||||
calculate_region_area(&self->screencopy.back->damage);
|
||||
|
@ -665,8 +676,13 @@ void wayvnc_process_frame(struct wayvnc* self)
|
|||
self->selected_output->transform,
|
||||
self->selected_output->width,
|
||||
self->selected_output->height);
|
||||
// damage_dump(stdout, &txdamage, width, height, 32);
|
||||
wayvnc_damage_region(self, &txdamage);
|
||||
|
||||
wv_damage_all_buffers(self, &txdamage);
|
||||
wayvnc_render_to_fb(self, fb);
|
||||
nvnc_display_set_buffer(self->nvnc_display, fb);
|
||||
nvnc_fb_unref(fb);
|
||||
nvnc_display_damage_region(self->nvnc_display, &txdamage);
|
||||
|
||||
pixman_region_fini(&refined);
|
||||
pixman_region_fini(&txdamage);
|
||||
|
||||
|
@ -763,12 +779,10 @@ static void on_perf_tick(void* obj)
|
|||
double area_avg = (double)self->damage_area_sum / (double)self->n_frames_captured;
|
||||
double relative_area_avg = 100.0 * area_avg / total_area;
|
||||
|
||||
printf("Frames captured: %"PRIu32", rendered: %"PRIu32", average reported frame damage: %.1f %%\n",
|
||||
self->n_frames_captured, self->n_frames_rendered,
|
||||
relative_area_avg);
|
||||
printf("Frames captured: %"PRIu32", average reported frame damage: %.1f %%\n",
|
||||
self->n_frames_captured, relative_area_avg);
|
||||
|
||||
self->n_frames_captured = 0;
|
||||
self->n_frames_rendered = 0;
|
||||
self->damage_area_sum = 0;
|
||||
}
|
||||
|
||||
|
@ -996,6 +1010,12 @@ int main(int argc, char* argv[])
|
|||
if (init_nvnc(&self, address, port, use_unix_socket) < 0)
|
||||
goto nvnc_failure;
|
||||
|
||||
self.fb_pool = nvnc_fb_pool_new(0, 0, 0);
|
||||
if (!self.fb_pool)
|
||||
goto buffer_pool_failure;
|
||||
|
||||
LIST_INIT(&self.fb_side_data_list);
|
||||
|
||||
if (self.screencopy.manager)
|
||||
screencopy_init(&self.screencopy);
|
||||
|
||||
|
@ -1008,8 +1028,6 @@ int main(int argc, char* argv[])
|
|||
data_control_init(&self.data_control, self.display, self.nvnc,
|
||||
self.selected_seat->wl_seat);
|
||||
|
||||
pixman_region_init(&self.current_damage);
|
||||
|
||||
self.screencopy.overlay_cursor = overlay_cursor;
|
||||
|
||||
if (wayvnc_start_capture(&self) < 0)
|
||||
|
@ -1028,13 +1046,9 @@ int main(int argc, char* argv[])
|
|||
|
||||
screencopy_stop(&self.screencopy);
|
||||
|
||||
if (self.buffer) {
|
||||
damage_refinery_destroy(&self.damage_refinery);
|
||||
nvnc_fb_unref(self.buffer);
|
||||
}
|
||||
|
||||
pixman_region_fini(&self.current_damage);
|
||||
damage_refinery_destroy(&self.damage_refinery);
|
||||
|
||||
nvnc_fb_pool_unref(self.fb_pool);
|
||||
nvnc_display_unref(self.nvnc_display);
|
||||
nvnc_close(self.nvnc);
|
||||
if (zwp_linux_dmabuf)
|
||||
|
@ -1055,6 +1069,8 @@ int main(int argc, char* argv[])
|
|||
return 0;
|
||||
|
||||
capture_failure:
|
||||
nvnc_fb_pool_unref(self.fb_pool);
|
||||
buffer_pool_failure:
|
||||
nvnc_display_unref(self.nvnc_display);
|
||||
nvnc_close(self.nvnc);
|
||||
nvnc_failure:
|
||||
|
|
Loading…
Reference in New Issue