Skip to content

Commit 6a03d55

Browse files
committed
Implement sync using NV_timeline_semaphore
1 parent 65c83d0 commit 6a03d55

File tree

6 files changed

+338
-53
lines changed

6 files changed

+338
-53
lines changed

src/capture.c

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ static struct {
3838
bool map_host;
3939
bool need_reinit;
4040
uint8_t device_uuid[16];
41+
bool enable_sem;
42+
uint32_t session;
43+
uint64_t wait_value;
44+
uint64_t signal_value;
4145
} data;
4246

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

118122
void capture_update_socket()
119123
{
120-
static int64_t last_check = 0;
121-
const int64_t now = os_time_get_nano();
122-
if (now - last_check < 1000000000) {
123-
return;
124+
if (!data.capturing) {
125+
static int64_t last_check = 0;
126+
const int64_t now = os_time_get_nano();
127+
if (now - last_check < 1000000000) {
128+
return;
129+
}
130+
last_check = now;
124131
}
125-
last_check = now;
126132

127133
if (data.connfd < 0 && !capture_try_connect()) {
128134
return;
@@ -131,18 +137,32 @@ void capture_update_socket()
131137
struct capture_control_data control;
132138
ssize_t n = recv(data.connfd, &control, sizeof(control), 0);
133139
if (n == sizeof(control)) {
134-
const bool old_no_modifiers = data.no_modifiers;
135-
const bool old_linear = data.linear;
136-
const bool old_map_host = data.map_host;
137-
data.accepted = control.capturing == 1;
138-
data.no_modifiers = control.no_modifiers == 1;
139-
data.linear = control.linear == 1;
140-
data.map_host = control.map_host == 1;
141-
memcpy(data.device_uuid, control.device_uuid, 16);
142-
if (data.capturing && (old_no_modifiers != data.no_modifiers
143-
|| old_linear != data.linear
144-
|| old_map_host != data.map_host)) {
145-
data.need_reinit = true;
140+
if (control.ex) {
141+
uint8_t buf[CAPTURE_SYNC_DATA_SIZE];
142+
n = recv(data.connfd, buf, sizeof(buf), 0);
143+
if (n > 1) {
144+
if (buf[0] == CAPTURE_SYNC_DATA_TYPE) {
145+
struct capture_sync_data *sync = (struct capture_sync_data *)buf;
146+
if (sync->session == data.session) {
147+
data.wait_value = sync->value;
148+
}
149+
}
150+
}
151+
} else {
152+
const bool old_no_modifiers = data.no_modifiers;
153+
const bool old_linear = data.linear;
154+
const bool old_map_host = data.map_host;
155+
data.accepted = control.capturing == 1;
156+
data.no_modifiers = control.no_modifiers == 1;
157+
data.linear = control.linear == 1;
158+
data.map_host = control.map_host == 1;
159+
data.enable_sem = control.enable_sem == 1;
160+
memcpy(data.device_uuid, control.device_uuid, 16);
161+
if (data.capturing && (old_no_modifiers != data.no_modifiers
162+
|| old_linear != data.linear
163+
|| old_map_host != data.map_host)) {
164+
data.need_reinit = true;
165+
}
146166
}
147167
}
148168
if (n == -1) {
@@ -163,20 +183,33 @@ void capture_update_socket()
163183
void capture_init_shtex(
164184
int width, int height, int format, int strides[4],
165185
int offsets[4], uint64_t modifier, uint32_t winid,
166-
bool flip, uint32_t color_space, int nfd, int fds[4])
186+
bool flip, uint32_t color_space, int nfd, int fds[4],
187+
int sem_fd)
167188
{
189+
int cfds[5];
190+
int num_planes = nfd;
191+
192+
for (int i = 0; i < nfd; i++) {
193+
cfds[i] = fds[i];
194+
}
195+
if (data.enable_sem && sem_fd >= 0) {
196+
cfds[nfd++] = sem_fd;
197+
}
198+
168199
struct capture_texture_data td = {0};
169200
td.type = CAPTURE_TEXTURE_DATA_TYPE;
170201
td.nfd = nfd;
171202
td.width = width;
172203
td.height = height;
173204
td.format = format;
174-
memcpy(td.strides, strides, sizeof(int) * nfd);
175-
memcpy(td.offsets, offsets, sizeof(int) * nfd);
205+
memcpy(td.strides, strides, sizeof(int) * num_planes);
206+
memcpy(td.offsets, offsets, sizeof(int) * num_planes);
176207
td.modifier = modifier;
177208
td.winid = winid;
178209
td.flip = flip;
179210
td.color_space = color_space;
211+
td.session = ++data.session;
212+
td.sem = data.enable_sem && sem_fd >= 0 ? num_planes : 0;
180213

181214
struct msghdr msg = {0};
182215

@@ -187,14 +220,14 @@ void capture_init_shtex(
187220
msg.msg_iov = &io;
188221
msg.msg_iovlen = 1;
189222

190-
char cmsg_buf[CMSG_SPACE(sizeof(int) * 4)];
223+
char cmsg_buf[CMSG_SPACE(sizeof(int) * 5)];
191224
msg.msg_control = cmsg_buf;
192225
msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfd);
193226
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
194227
cmsg->cmsg_level = SOL_SOCKET;
195228
cmsg->cmsg_type = SCM_RIGHTS;
196229
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * nfd);
197-
memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * nfd);
230+
memcpy(CMSG_DATA(cmsg), cfds, sizeof(int) * nfd);
198231

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

204237
data.capturing = true;
205238
data.need_reinit = false;
239+
data.wait_value = 0;
240+
data.signal_value = 0;
206241
}
207242

208243
void capture_stop()
@@ -225,6 +260,39 @@ bool capture_ready()
225260
return data.capturing;
226261
}
227262

263+
bool capture_should_render(uint64_t *wait, uint64_t *signal)
264+
{
265+
if (data.enable_sem && data.wait_value < data.signal_value) {
266+
return false;
267+
}
268+
*wait = data.enable_sem ? data.wait_value : data.signal_value;
269+
*signal = data.signal_value + 2;
270+
return true;
271+
}
272+
273+
void capture_render_done()
274+
{
275+
data.signal_value += 2;
276+
277+
struct capture_sync_data sd = {0};
278+
sd.type = CAPTURE_SYNC_DATA_TYPE;
279+
sd.session = data.session;
280+
sd.value = data.signal_value;
281+
282+
struct msghdr msg = {0};
283+
struct iovec io = {
284+
.iov_base = &sd,
285+
.iov_len = CAPTURE_SYNC_DATA_SIZE,
286+
};
287+
msg.msg_iov = &io;
288+
msg.msg_iovlen = 1;
289+
290+
const ssize_t sent = sendmsg(data.connfd, &msg, MSG_NOSIGNAL);
291+
if (sent < 0) {
292+
hlog("Socket sendmsg error %s", strerror(errno));
293+
}
294+
}
295+
228296
bool capture_allocate_no_modifiers()
229297
{
230298
return data.no_modifiers;

src/capture.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ struct capture_texture_data {
6969
uint32_t winid;
7070
uint8_t flip;
7171
uint32_t color_space;
72-
uint8_t padding[65];
72+
uint32_t session;
73+
uint8_t sem;
74+
uint8_t padding[60];
7375
} __attribute__((packed));
7476

7577
#define CAPTURE_TEXTURE_DATA_TYPE 11
@@ -82,25 +84,42 @@ struct capture_control_data {
8284
uint8_t linear;
8385
uint8_t map_host;
8486
uint8_t device_uuid[16];
85-
uint8_t padding[12];
87+
uint8_t ex;
88+
uint8_t enable_sem;
89+
uint8_t padding[10];
8690
} __attribute__((packed));
8791

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

96+
struct capture_sync_data {
97+
uint8_t type;
98+
uint32_t session;
99+
uint64_t value;
100+
uint8_t padding[19];
101+
} __attribute__((packed));
102+
103+
#define CAPTURE_SYNC_DATA_TYPE 12
104+
#define CAPTURE_SYNC_DATA_SIZE 32
105+
static_assert(sizeof(struct capture_sync_data) == CAPTURE_SYNC_DATA_SIZE, "size mismatch");
106+
92107
void capture_init();
93108
void capture_update_socket();
94109
void capture_init_shtex(
95110
int width, int height, int format, int strides[4],
96111
int offsets[4], uint64_t modifier, uint32_t winid,
97-
bool flip, uint32_t color_space, int nfd, int fds[4]);
112+
bool flip, uint32_t color_space, int nfd, int fds[4],
113+
int sem_fd);
98114
void capture_stop();
99115

100116
bool capture_should_stop();
101117
bool capture_should_init();
102118
bool capture_ready();
103119

120+
bool capture_should_render(uint64_t *wait, uint64_t *signal);
121+
void capture_render_done();
122+
104123
bool capture_allocate_no_modifiers();
105124
bool capture_allocate_linear();
106125
bool capture_allocate_map_host();

src/glinject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ static bool gl_init(void *display, void *surface)
969969

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

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

0 commit comments

Comments
 (0)