Capture a new frame immediately when a client requests a whole frame
parent
ee4917f200
commit
238c196e6b
|
@ -31,6 +31,10 @@ enum frame_capture_status {
|
|||
CAPTURE_DONE,
|
||||
};
|
||||
|
||||
enum frame_capture_options {
|
||||
CAPTURE_NOW = 1 << 0,
|
||||
};
|
||||
|
||||
struct frame_capture {
|
||||
enum frame_capture_status status;
|
||||
|
||||
|
@ -57,14 +61,14 @@ struct frame_capture {
|
|||
struct {
|
||||
void (*render)(struct frame_capture*, struct renderer*,
|
||||
struct nvnc_fb* fb);
|
||||
int (*start)(struct frame_capture*);
|
||||
int (*start)(struct frame_capture*, enum frame_capture_options);
|
||||
void (*stop)(struct frame_capture*);
|
||||
} backend;
|
||||
};
|
||||
|
||||
static inline int frame_capture_start(struct frame_capture* self)
|
||||
static inline int frame_capture_start(struct frame_capture* self, enum frame_capture_options options)
|
||||
{
|
||||
return self->backend.start(self);
|
||||
return self->backend.start(self, options);
|
||||
}
|
||||
|
||||
static inline void frame_capture_stop(struct frame_capture* self)
|
||||
|
|
|
@ -55,6 +55,7 @@ struct screencopy {
|
|||
|
||||
struct smooth delay_smoother;
|
||||
double delay;
|
||||
bool is_immediate_copy;
|
||||
};
|
||||
|
||||
void screencopy_init(struct screencopy* self);
|
||||
|
|
|
@ -133,7 +133,7 @@ static void dmabuf_frame_ready(void* data,
|
|||
if (time_left >= 0.0) {
|
||||
aml_set_duration(self->timer, time_left);
|
||||
aml_start(aml_get_default(), self->timer);
|
||||
frame_capture_start(fc);
|
||||
frame_capture_start(fc, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,8 @@ static void dmabuf_frame_cancel(void* data,
|
|||
dmabuf_close_fds(self);
|
||||
}
|
||||
|
||||
static int dmabuf_capture_start(struct frame_capture* fc)
|
||||
static int dmabuf_capture_start(struct frame_capture* fc,
|
||||
enum frame_capture_options options)
|
||||
{
|
||||
struct dmabuf_capture* self = (void*)fc;
|
||||
|
||||
|
|
27
src/main.c
27
src/main.c
|
@ -35,6 +35,7 @@
|
|||
#include <pixman.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "frame-capture.h"
|
||||
#include "wlr-export-dmabuf-unstable-v1.h"
|
||||
#include "wlr-screencopy-unstable-v1.h"
|
||||
#include "wlr-virtual-pointer-unstable-v1.h"
|
||||
|
@ -438,8 +439,11 @@ static void on_fb_req(struct nvnc_client* client, bool is_incremental,
|
|||
struct wayvnc* self = nvnc_get_userdata(nvnc);
|
||||
|
||||
// TODO: Make this per-client rather than global
|
||||
if (!is_incremental)
|
||||
if (!is_incremental) {
|
||||
self->please_send_full_frame_next = true;
|
||||
frame_capture_stop(self->capture_backend);
|
||||
frame_capture_start(self->capture_backend, CAPTURE_NOW);
|
||||
}
|
||||
}
|
||||
|
||||
int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port)
|
||||
|
@ -475,9 +479,9 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int wayvnc_start_capture(struct wayvnc* self)
|
||||
int wayvnc_start_capture(struct wayvnc* self, enum frame_capture_options opt)
|
||||
{
|
||||
return frame_capture_start(self->capture_backend);
|
||||
return frame_capture_start(self->capture_backend, opt);
|
||||
}
|
||||
|
||||
static void on_damage_check_done(struct pixman_region16* damage, void* userdata)
|
||||
|
@ -491,10 +495,16 @@ static void on_damage_check_done(struct pixman_region16* damage, void* userdata)
|
|||
|
||||
struct nvnc_fb* fb = get_current_fb(self);
|
||||
uint32_t* addr = nvnc_fb_get_addr(fb);
|
||||
uint32_t fb_width = nvnc_fb_get_width(get_current_fb(self));
|
||||
uint32_t fb_width = nvnc_fb_get_width(fb);
|
||||
uint32_t fb_height = nvnc_fb_get_height(fb);
|
||||
|
||||
renderer_read_frame(&self->renderer, addr + y * fb_width, y,
|
||||
damage_height);
|
||||
|
||||
if (damage_height != fb_height)
|
||||
nvnc_fb_set_flags(fb, nvnc_fb_get_flags(fb) |
|
||||
NVNC_FB_PARTIAL);
|
||||
|
||||
nvnc_fb_unlock(fb);
|
||||
|
||||
nvnc_feed_frame(self->nvnc, fb, damage);
|
||||
|
@ -503,7 +513,7 @@ static void on_damage_check_done(struct pixman_region16* damage, void* userdata)
|
|||
nvnc_fb_unlock(get_current_fb(self));
|
||||
}
|
||||
|
||||
if (wayvnc_start_capture(self) < 0) {
|
||||
if (wayvnc_start_capture(self, 0) < 0) {
|
||||
log_error("Failed to start capture. Exiting...\n");
|
||||
wayvnc_exit(self);
|
||||
}
|
||||
|
@ -577,6 +587,7 @@ void wayvnc_process_frame(struct wayvnc* self)
|
|||
|
||||
void* addr = nvnc_fb_get_addr(fb);
|
||||
renderer_read_frame(&self->renderer, addr, 0, height);
|
||||
nvnc_fb_set_flags(fb, nvnc_fb_get_flags(fb) & ~NVNC_FB_PARTIAL);
|
||||
nvnc_fb_unlock(fb);
|
||||
|
||||
struct pixman_region16 damage;
|
||||
|
@ -586,7 +597,7 @@ void wayvnc_process_frame(struct wayvnc* self)
|
|||
pixman_region_fini(&damage);
|
||||
|
||||
done:
|
||||
if (wayvnc_start_capture(self) < 0) {
|
||||
if (wayvnc_start_capture(self, 0) < 0) {
|
||||
log_error("Failed to start capture. Exiting...\n");
|
||||
wayvnc_exit(self);
|
||||
}
|
||||
|
@ -608,7 +619,7 @@ void on_capture_done(struct frame_capture* capture)
|
|||
wayvnc_exit(self);
|
||||
break;
|
||||
case CAPTURE_FAILED:
|
||||
if (wayvnc_start_capture(self) < 0) {
|
||||
if (wayvnc_start_capture(self, CAPTURE_NOW) < 0) {
|
||||
log_error("Failed to start capture. Exiting...\n");
|
||||
wayvnc_exit(self);
|
||||
}
|
||||
|
@ -885,7 +896,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
self.capture_backend->overlay_cursor = overlay_cursor;
|
||||
|
||||
if (wayvnc_start_capture(&self) < 0)
|
||||
if (wayvnc_start_capture(&self, 0) < 0)
|
||||
goto capture_failure;
|
||||
|
||||
wl_display_dispatch(self.display);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <libdrm/drm_fourcc.h>
|
||||
#include <aml.h>
|
||||
|
||||
#include "frame-capture.h"
|
||||
#include "shm.h"
|
||||
#include "screencopy.h"
|
||||
#include "smooth.h"
|
||||
|
@ -91,6 +92,8 @@ static void screencopy_stop(struct frame_capture* fc)
|
|||
|
||||
aml_stop(aml_get_default(), self->timer);
|
||||
|
||||
self->frame_capture.status = CAPTURE_STOPPED;
|
||||
|
||||
if (self->frame) {
|
||||
zwlr_screencopy_frame_v1_destroy(self->frame);
|
||||
self->frame = NULL;
|
||||
|
@ -116,7 +119,11 @@ static void screencopy_buffer(void* data,
|
|||
self->frame_capture.frame_info.height = height;
|
||||
self->frame_capture.frame_info.stride = stride;
|
||||
|
||||
zwlr_screencopy_frame_v1_copy_with_damage(self->frame, self->buffer);
|
||||
if (self->is_immediate_copy)
|
||||
zwlr_screencopy_frame_v1_copy(self->frame, self->buffer);
|
||||
else
|
||||
zwlr_screencopy_frame_v1_copy_with_damage(self->frame,
|
||||
self->buffer);
|
||||
}
|
||||
|
||||
static void screencopy_flags(void* data,
|
||||
|
@ -149,6 +156,15 @@ static void screencopy_ready(void* data,
|
|||
double delay = (self->last_time - self->start_time) * 1.0e-6;
|
||||
self->delay = smooth(&self->delay_smoother, delay);
|
||||
|
||||
if (self->is_immediate_copy) {
|
||||
self->frame_capture.damage_hint.x = 0;
|
||||
self->frame_capture.damage_hint.y = 0;
|
||||
self->frame_capture.damage_hint.width =
|
||||
self->frame_capture.frame_info.width;
|
||||
self->frame_capture.damage_hint.height =
|
||||
self->frame_capture.frame_info.height;
|
||||
}
|
||||
|
||||
self->frame_capture.status = CAPTURE_DONE;
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
}
|
||||
|
@ -217,13 +233,16 @@ static void screencopy__poll(void* obj)
|
|||
screencopy__start_capture(fc);
|
||||
}
|
||||
|
||||
static int screencopy_start(struct frame_capture* fc)
|
||||
static int screencopy_start(struct frame_capture* fc,
|
||||
enum frame_capture_options options)
|
||||
{
|
||||
struct screencopy* self = (void*)fc;
|
||||
|
||||
if (fc->status == CAPTURE_IN_PROGRESS)
|
||||
return -1;
|
||||
|
||||
self->is_immediate_copy = !!(options & CAPTURE_NOW);
|
||||
|
||||
uint64_t now = gettime_us();
|
||||
double dt = (now - self->last_time) * 1.0e-6;
|
||||
double time_left = (1.0 / RATE_LIMIT - dt - self->delay) * 1.0e3;
|
||||
|
|
Loading…
Reference in New Issue