@@ -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
4347static bool get_wine_exe (char * buf , size_t bufsize )
@@ -117,12 +121,14 @@ void capture_init()
117121
118122void 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()
163183void 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
208243void 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+
228296bool capture_allocate_no_modifiers ()
229297{
230298 return data .no_modifiers ;
0 commit comments