Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 90 additions & 22 deletions src/capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ static struct {
bool map_host;
bool need_reinit;
uint8_t device_uuid[16];
bool enable_sem;
uint32_t session;
uint64_t wait_value;
uint64_t signal_value;
} data;

static bool get_wine_exe(char *buf, size_t bufsize)
Expand Down Expand Up @@ -117,12 +121,14 @@ void capture_init()

void capture_update_socket()
{
static int64_t last_check = 0;
const int64_t now = os_time_get_nano();
if (now - last_check < 1000000000) {
return;
if (!data.capturing) {
static int64_t last_check = 0;
const int64_t now = os_time_get_nano();
if (now - last_check < 1000000000) {
return;
}
last_check = now;
}
last_check = now;

if (data.connfd < 0 && !capture_try_connect()) {
return;
Expand All @@ -131,18 +137,32 @@ void capture_update_socket()
struct capture_control_data control;
ssize_t n = recv(data.connfd, &control, sizeof(control), 0);
if (n == sizeof(control)) {
const bool old_no_modifiers = data.no_modifiers;
const bool old_linear = data.linear;
const bool old_map_host = data.map_host;
data.accepted = control.capturing == 1;
data.no_modifiers = control.no_modifiers == 1;
data.linear = control.linear == 1;
data.map_host = control.map_host == 1;
memcpy(data.device_uuid, control.device_uuid, 16);
if (data.capturing && (old_no_modifiers != data.no_modifiers
|| old_linear != data.linear
|| old_map_host != data.map_host)) {
data.need_reinit = true;
if (control.ex) {
uint8_t buf[CAPTURE_SYNC_DATA_SIZE];
n = recv(data.connfd, buf, sizeof(buf), 0);
if (n > 1) {
if (buf[0] == CAPTURE_SYNC_DATA_TYPE) {
struct capture_sync_data *sync = (struct capture_sync_data *)buf;
if (sync->session == data.session) {
data.wait_value = sync->value;
}
}
}
} else {
const bool old_no_modifiers = data.no_modifiers;
const bool old_linear = data.linear;
const bool old_map_host = data.map_host;
data.accepted = control.capturing == 1;
data.no_modifiers = control.no_modifiers == 1;
data.linear = control.linear == 1;
data.map_host = control.map_host == 1;
data.enable_sem = control.enable_sem == 1;
memcpy(data.device_uuid, control.device_uuid, 16);
if (data.capturing && (old_no_modifiers != data.no_modifiers
|| old_linear != data.linear
|| old_map_host != data.map_host)) {
data.need_reinit = true;
}
}
}
if (n == -1) {
Expand All @@ -163,20 +183,33 @@ void capture_update_socket()
void capture_init_shtex(
int width, int height, int format, int strides[4],
int offsets[4], uint64_t modifier, uint32_t winid,
bool flip, uint32_t color_space, int nfd, int fds[4])
bool flip, uint32_t color_space, int nfd, int fds[4],
int sem_fd)
{
int cfds[5];
int num_planes = nfd;

for (int i = 0; i < nfd; i++) {
cfds[i] = fds[i];
}
if (data.enable_sem && sem_fd >= 0) {
cfds[nfd++] = sem_fd;
}

struct capture_texture_data td = {0};
td.type = CAPTURE_TEXTURE_DATA_TYPE;
td.nfd = nfd;
td.width = width;
td.height = height;
td.format = format;
memcpy(td.strides, strides, sizeof(int) * nfd);
memcpy(td.offsets, offsets, sizeof(int) * nfd);
memcpy(td.strides, strides, sizeof(int) * num_planes);
memcpy(td.offsets, offsets, sizeof(int) * num_planes);
td.modifier = modifier;
td.winid = winid;
td.flip = flip;
td.color_space = color_space;
td.session = ++data.session;
td.sem = data.enable_sem && sem_fd >= 0 ? num_planes : 0;

struct msghdr msg = {0};

Expand All @@ -187,14 +220,14 @@ void capture_init_shtex(
msg.msg_iov = &io;
msg.msg_iovlen = 1;

char cmsg_buf[CMSG_SPACE(sizeof(int) * 4)];
char cmsg_buf[CMSG_SPACE(sizeof(int) * 5)];
msg.msg_control = cmsg_buf;
msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfd);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * nfd);
memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * nfd);
memcpy(CMSG_DATA(cmsg), cfds, sizeof(int) * nfd);

const ssize_t sent = sendmsg(data.connfd, &msg, MSG_NOSIGNAL);
if (sent < 0) {
Expand All @@ -203,6 +236,8 @@ void capture_init_shtex(

data.capturing = true;
data.need_reinit = false;
data.wait_value = 0;
data.signal_value = 0;
}

void capture_stop()
Expand All @@ -225,6 +260,39 @@ bool capture_ready()
return data.capturing;
}

bool capture_should_render(uint64_t *wait, uint64_t *signal)
{
if (data.enable_sem && data.wait_value < data.signal_value) {
return false;
}
*wait = data.enable_sem ? data.wait_value : data.signal_value;
*signal = data.signal_value + 2;
return true;
}

void capture_render_done()
{
data.signal_value += 2;

struct capture_sync_data sd = {0};
sd.type = CAPTURE_SYNC_DATA_TYPE;
sd.session = data.session;
sd.value = data.signal_value;

struct msghdr msg = {0};
struct iovec io = {
.iov_base = &sd,
.iov_len = CAPTURE_SYNC_DATA_SIZE,
};
msg.msg_iov = &io;
msg.msg_iovlen = 1;

const ssize_t sent = sendmsg(data.connfd, &msg, MSG_NOSIGNAL);
if (sent < 0) {
hlog("Socket sendmsg error %s", strerror(errno));
}
}

bool capture_allocate_no_modifiers()
{
return data.no_modifiers;
Expand Down
25 changes: 22 additions & 3 deletions src/capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ struct capture_texture_data {
uint32_t winid;
uint8_t flip;
uint32_t color_space;
uint8_t padding[65];
uint32_t session;
uint8_t sem;
uint8_t padding[60];
} __attribute__((packed));

#define CAPTURE_TEXTURE_DATA_TYPE 11
Expand All @@ -82,25 +84,42 @@ struct capture_control_data {
uint8_t linear;
uint8_t map_host;
uint8_t device_uuid[16];
uint8_t padding[12];
uint8_t ex;
uint8_t enable_sem;
uint8_t padding[10];
} __attribute__((packed));

#define CAPTURE_CONTROL_DATA_TYPE 10
#define CAPTURE_CONTROL_DATA_SIZE 32
static_assert(sizeof(struct capture_control_data) == CAPTURE_CONTROL_DATA_SIZE, "size mismatch");

struct capture_sync_data {
uint8_t type;
uint32_t session;
uint64_t value;
uint8_t padding[19];
} __attribute__((packed));

#define CAPTURE_SYNC_DATA_TYPE 12
#define CAPTURE_SYNC_DATA_SIZE 32
static_assert(sizeof(struct capture_sync_data) == CAPTURE_SYNC_DATA_SIZE, "size mismatch");

void capture_init();
void capture_update_socket();
void capture_init_shtex(
int width, int height, int format, int strides[4],
int offsets[4], uint64_t modifier, uint32_t winid,
bool flip, uint32_t color_space, int nfd, int fds[4]);
bool flip, uint32_t color_space, int nfd, int fds[4],
int sem_fd);
void capture_stop();

bool capture_should_stop();
bool capture_should_init();
bool capture_ready();

bool capture_should_render(uint64_t *wait, uint64_t *signal);
void capture_render_done();

bool capture_allocate_no_modifiers();
bool capture_allocate_linear();
bool capture_allocate_map_host();
Expand Down
2 changes: 1 addition & 1 deletion src/glinject.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ static bool gl_init(void *display, void *surface)

capture_init_shtex(data.width, data.height, data.buf_fourcc,
data.buf_strides, data.buf_offsets, data.buf_modifier,
data.winid, /*flip*/true, 0, data.nfd, data.buf_fds);
data.winid, /*flip*/true, 0, data.nfd, data.buf_fds, -1);

hlog("------------------ opengl capture started ------------------");

Expand Down
Loading