1 /*
2  Arcan Shared Memory Interface
3 
4  Copyright (c) 2012-2018, Bjorn Stahl
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms,
8  with or without modification, are permitted provided that the
9  following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice,
12  this list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  3. Neither the name of the copyright holder nor the names of its contributors
19  may be used to endorse or promote products derived from this software without
20  specific prior written permission.
21 
22  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #ifndef _HAVE_ARCAN_SHMIF_CONTROL
36 #define _HAVE_ARCAN_SHMIF_CONTROL
37 
38 /*
39  * This header defines the interface and support functions for
40  * shared memory- based communication between the arcan parent
41  * and frameservers/non-authoritative clients.
42  *
43  * For extended documentation on how this interface works, design
44  * rationale, changes and so on, please refer to the wiki @
45  * https://github.com/letoram/arcan/wiki/Shmif
46  */
47 
48 /*
49  * This prefix is used over HOME only if no explicit path was provided
50  * and there is no XDG_RUNTIME_DIR to use.
51  */
52 #ifndef ARCAN_SHMIF_PREFIX
53 #define ARCAN_SHMIF_PREFIX ".arcan/."
54 #endif
55 
56 /*
57  * Default permissions / mask that listening sockets will be created under
58  */
59 #ifndef ARCAN_SHM_UMASK
60 #define ARCAN_SHM_UMASK (S_IRWXU | S_IRWXG)
61 #endif
62 
63 /*
64  * Compile-time constants that define the size and layout
65  * of the shared structure. These values are part in defining the ABI
66  * and should therefore only be tuned when you have control of the
67  * whole-system compilation and packaging (OS distributions, embedded
68  * systems).
69  */
70 
71 /*
72  * Define the reserved ring-buffer space used for input and output events
73  * must be 0 < PP_QUEUE_SZ < 256
74  */
75 #ifndef PP_QUEUE_SZ
76 #define PP_QUEUE_SZ 127
77 #endif
78 static const int ARCAN_SHMIF_QUEUE_SZ = PP_QUEUE_SZ;
79 
80 /*
81  * Audio format and basic parameters, this is kept primitive on purpose.
82  * This will be revised shortly, but modifying still breaks ABI and may
83  * break current frameservers.
84  */
85 #ifndef AUDIO_SAMPLE_TYPE
86 #define AUDIO_SAMPLE_TYPE int16_t
87 #endif
88 
89 /*
90  * ALWAYS interleaved. for later quality work, all the video/audio
91  * buffer format tuning and indirection macros will be moved to separate
92  * selectable profile headers, and the packing macros will be redone
93  * using C11 type-generic macros.
94  */
95 typedef AUDIO_SAMPLE_TYPE shmif_asample;
96 static const int ARCAN_SHMIF_SAMPLERATE = 48000;
97 static const int ARCAN_SHMIF_ACHANNELS = 2;
98 
99 #ifndef SHMIF_AFLOAT
100 #define SHMIF_AFLOAT(X) ( (int16_t) ((X) * 32767.0) ) /* sacrifice -32768 */
101 #endif
102 
103 #ifndef SHMIF_AINT16
104 #define SHMIF_AINT16(X) ( (int16_t) ((X)) )
105 #endif
106 
107 /*
108  * These limits affect ABI as we need to track how much is used in each
109  * audiobuffer slot
110  */
111 #define ARCAN_SHMIF_ABUFC_LIM 12
112 #define ARCAN_SHMIF_VBUFC_LIM 3
113 /*
114  * These are technically limited by the combination of graphics and video
115  * platforms. Since the buffers are placed at the end of the struct, they
116  * can be changed without breaking ABI though several resize requests may
117  * be rejected.
118  */
119 #ifndef PP_SHMPAGE_MAXW
120 #define PP_SHMPAGE_MAXW 8192
121 #endif
122 static const int ARCAN_SHMPAGE_MAXW = PP_SHMPAGE_MAXW;
123 
124 #ifndef PP_SHMPAGE_MAXH
125 #define PP_SHMPAGE_MAXH 8192
126 #endif
127 static const int ARCAN_SHMPAGE_MAXH = PP_SHMPAGE_MAXH;
128 
129 /*
130  * Identification token that may need to be passed when making a socket
131  * connection to the main arcan process.
132  */
133 #ifndef PP_SHMPAGE_SHMKEYLIM
134 #define PP_SHMPAGE_SHMKEYLIM 32
135 #endif
136 
137 /*
138  * We abstract the base type for a pixel and provide a packing macro in order
139  * to permit systems with lower memory to switch to uint16 RGB565 style
140  * formats, and to permit future switches to higher depth/range.  The
141  * separation between video_platform definition of these macros also allows a
142  * comparison between engine internals and interface to warn or convert.
143  */
144 #ifndef VIDEO_PIXEL_TYPE
145 #define VIDEO_PIXEL_TYPE uint32_t
146 #endif
147 
148 #ifndef ARCAN_SHMPAGE_VCHANNELS
149 #define ARCAN_SHMPAGE_VCHANNELS 4
150 #endif
151 
152 #ifndef ARCAN_SHMPAGE_DEFAULT_PPCM
153 #define ARCAN_SHMPAGE_DEFAULT_PPCM 37.795276
154 #endif
155 
156 static const float shmif_ppcm_default = ARCAN_SHMPAGE_DEFAULT_PPCM;
157 
158 typedef VIDEO_PIXEL_TYPE shmif_pixel;
159 
160 /*
161  * Reasonable starting dimensions, this can be changed without breaking ABI
162  * as parent/client will initiate a resize based on gain relative to the
163  * current size.
164  *
165  * It should, at least, fit 32*32*sizeof(shmif_pixel) + sizeof(struct) +
166  * sizeof event*PP_QUEUE_SIZE*2 + PP_AUDIOBUF_SZ with alignment padding.
167  */
168 #ifndef PP_SHMPAGE_STARTSZ
169 #define PP_SHMPAGE_STARTSZ 2014088
170 #endif
171 
172 /*
173  * This is to constrain a single segment from consuming too much memory,
174  * though it also plays a big role in OVERCOMMIT builds where single segment
175  * size is fixed and will always consume this amount.
176  */
177 #ifndef PP_SHMPAGE_MAXSZ
178 #define PP_SHMPAGE_MAXSZ 104857600
179 #endif
180 static const int ARCAN_SHMPAGE_MAX_SZ = PP_SHMPAGE_MAXSZ;
181 
182 /*
183  * Overcommit is a specialized build mode (that should be avoided if possible)
184  * that sets the initial segment size to PP_SHMPAGE_STARTSZ and no new buffer
185  * dimension negotiation will occur. This is needed for shitty platforms that
186  * don't provide the means for resizing a handle- backed memory mapped store.
187  * Not to point any fingers, but system-level OSX is a pile of shit.
188  */
189 #ifdef ARCAN_SHMIF_OVERCOMMIT
190 static const int ARCAN_SHMPAGE_START_SZ = PP_SHMPAGE_MAXSZ;
191 #else
192 static const int ARCAN_SHMPAGE_START_SZ = PP_SHMPAGE_STARTSZ;
193 #endif
194 
195 #ifndef PP_SHMPAGE_ALIGN
196 #define PP_SHMPAGE_ALIGN 64
197 #endif
198 static const int ARCAN_SHMPAGE_ALIGN = PP_SHMPAGE_ALIGN;
199 
200 /*
201  * Two primary transfer operation types, from the perspective of the
202  * main arcan application (i.e. normally frameservers feed INPUT but
203  * specialized recording segments are flagged as OUTPUT. Internally,
204  * these have different synchronization rules.
205  */
206 enum arcan_shmif_type {
207 	SHMIF_INPUT = 1,
208 	SHMIF_OUTPUT
209 };
210 
211 /*
212  * This enum defines the possible operations for audio and video
213  * synchronization (both or either) and how locking should behave.
214  */
215 enum arcan_shmif_sigmask {
216 	SHMIF_SIGVID = 1,
217 	SHMIF_SIGAUD = 2,
218 
219 /* synchronous, wait for parent to acknowledge
220  * (assuming there are no more buffers available) */
221 	SHMIF_SIGBLK_FORCE = 0,
222 
223 /* Extra flag, always return immediately, further writes may cause
224  * tearing and other visual/aural artifacts */
225 	SHMIF_SIGBLK_NONE  = 4,
226 
227 /* For >= 2 buffered contexts, compare the current to the previous submitted
228  * buffer and shrink the dirty region to the boundary of the actually changed
229  * context. If there are no visible changes, the signalling will return
230  * immediately. This will only work if the buffer history is complete and no
231  * manual dirty management has been applied. */
232 	SHMIF_SIGVID_AUTO_DIRTY = 8,
233 };
234 
235 struct arcan_shmif_cont;
236 struct shmif_ext_hidden;
237 struct arcan_shmif_page;
238 struct arcan_shmif_initial;
239 
240 typedef enum arcan_shmif_sigmask(
241 	*shmif_trigger_hook)(struct arcan_shmif_cont*);
242 
243 typedef void (*shmif_reset_hook)(int state, void* tag);
244 
245 enum ARCAN_FLAGS {
246 	SHMIF_NOFLAGS = 0,
247 
248 /* by default, the connection IPC resources are unlinked, this
249  * may not always be desired (debugging, monitoring, ...) */
250 	SHMIF_DONT_UNLINK = 1,
251 
252 /* a guard thread is usually allocated to monitor the status of
253  * the server, setting this flag explicitly prevents the creation of
254  * that thread */
255 	SHMIF_DISABLE_GUARD = 2,
256 
257 /* failure to acquire a segment should be exit(EXIT_FAILURE); */
258 	SHMIF_ACQUIRE_FATALFAIL = 4,
259 
260 /* if FATALFAIL, do we have a custom function? should be first argument */
261 	SHMIF_FATALFAIL_FUNC = 8,
262 
263 /* set to sleep- try spin until a connection is established */
264 	SHMIF_CONNECT_LOOP = 16,
265 
266 /* don't implement pause/resume management in backend, forward the
267  * events to frontend */
268 	SHMIF_MANUAL_PAUSE = 32,
269 
270 /* On crash or disconnect, wait and try to reconnect. If successful,
271  * a _RESET event will be enqueued locally with ioev[0].iv == 3.
272  * Subsegments will still be lost, and if the connection has been set-up
273  * inherited+anonymous, this will still exit like normally. Set this
274  * flag to disable RECONNECT attempts entirely. */
275 	SHMIF_NOAUTO_RECONNECT = 64,
276 
277 /* for use as flag input to shmif_migrate calls, the default behavior
278  * is to only permit migration of the primary segment as there are
279  * further client considerations when secondary segments run in different
280  * threads along with the problem if subsegment requests are rejected */
281 	SHMIF_MIGRATE_SUBSEGMENTS = 128,
282 
283 /*
284  * When a connection is initiated, a number of events are gathered until
285  * the connection is activated (see arcan_shmif_initial) to determine
286  * costly properties in advance. By default, this also sets the initial
287  * size of the segment. Set this flag during connection if this behavior
288  * would be ignored/overridden by a manual- "data-source controlled"
289  * size.
290  */
291 	SHMIF_NOACTIVATE_RESIZE = 256,
292 
293 /*
294  * Setting this flag disables the internal management preroll stage entirely
295  */
296 	SHMIF_NOACTIVATE = 512,
297 
298 /* Setting this flag will avoid sending the register event on acquire */
299 	SHMIF_NOREGISTER = 1024
300 };
301 
302 /*
303  * Convenience wrapper function of checking environment variables
304  * for packed arguments, connection path / key etc.
305  *
306  * Will also clean-up / reset related environments
307  * to prevent propagation.
308  *
309  * If no arguments could be unpacked, *arg_arr will be set to NULL.
310  * If type is set to 0, no REGISTER event will be sent and you will
311  * need to send one manually. arg_arr livespan is tied to the _cont
312  * so the caller should not free or alias.
313  *
314  * If the [type] is not set, the connection will not wait for
315  * activation and the initial function will not provide anything
316  * useful.
317  */
318 struct arg_arr;
319 struct arcan_shmif_cont arcan_shmif_open(
320 	enum ARCAN_SEGID type, enum ARCAN_FLAGS flags, struct arg_arr**);
321 
322 /*
323  * Retrieve a reference to the argument- array that was built
324  * during shmif_open. May fail (return NULL) on an invalid context
325  * or if no arguments could be unpacked at open time.
326  */
327 struct arg_arr* arcan_shmif_args(struct arcan_shmif_cont*);
328 
329 /*
330  * Similar to resize_ext, developed to work around some shortcomings
331  * in the initial version without breaking ABI. Adds some improvements
332  * to the register/connect approach.
333  *
334  * use like shmif_open, but pass a prefilled struct like below,
335  * along with its sizeof(struct smif_open_ext)
336  */
337 struct shmif_open_ext {
338 	enum ARCAN_SEGID type;
339 	const char* title;
340 	const char* ident;
341 	uint64_t guid[2];
342 };
343 struct arcan_shmif_cont arcan_shmif_open_ext(
344 	enum ARCAN_FLAGS flags, struct arg_arr**,
345 	struct shmif_open_ext, size_t ext_sz);
346 
347 /*
348  * If the context has been opened with the SHMIF_DONT_UNLINK flag, any
349  * named resources are still accessible. This is used for some corner
350  * cases where one client should be able to monitor another and so on.
351  * This function attempts to unlink any named resources tied to the
352  * context [c].
353  */
354 void arcan_shmif_unlink(struct arcan_shmif_cont* c);
355 
356 /*
357  * accessor to the internal tracked segment mapping key (applicable
358  * to arcan_shmif_unlink and SHMIF_DONT_UNLINK). Will return NULL if
359  * the key has been unlinked.
360  */
361 const char* arcan_shmif_segment_key(struct arcan_shmif_cont* c);
362 
363 /*
364  * arcan_shmif_initial can be used to access initial configured
365  * settings (see struct arcan_shmif_initial for details). These values
366  * are only valid AFTER a successful call to arcan_shmif_open and ONLY
367  * until the first _poll or _wait call.
368  *
369  * REMEMBER to arcan_shmif_dupfd() on the fonts and render-nodes you
370  * want to keep and use as they will be closed, or set the fields to
371  * -1 to indicate that you take responsibility.
372  *
373  * RETURNS the number of bytes in struct (should == sizeof(struct
374  * arcan_shmif_initial, if larger, your code is using dated headers)
375  * or 0,NULL on failure (bad _cont or _enqueue/ _poll/_wait has been
376  * called).
377  */
378 size_t arcan_shmif_initial(struct arcan_shmif_cont*,
379 	struct arcan_shmif_initial**);
380 
381 /*
382  * This is used to make a non-authoritative connection using
383  * a domain- socket as a connection point (as specified by the
384  * connpath and optional connkey).
385  *
386  * Will return NULL or a user-managed string with a key
387  * suitable for shmkey, along with a file descriptor to the
388  * connected socket in *conn_ch
389  */
390 char* arcan_shmif_connect(const char* connpath,
391 	const char* connkey, file_handle* conn_ch);
392 
393 /*
394  * This is used to migrate a current connection, authoritative or not,
395  * to a non-authoritate connection, possibly using a different connection
396  * path and primitive.
397  *
398  * Will return false on invalid [cont] argument.
399  *
400  * Current limitations are that subsegments are not re-negotiated.
401  * Will return true or false depending on if the transfer was successful
402  * or not. If it failed, the referenced main connection is still valid.
403  */
404 enum shmif_migrate_status {
405 	SHMIF_MIGRATE_OK = 0,
406 	SHMIF_MIGRATE_BADARG = -1,
407 	SHMIF_MIGRATE_NOCON = -2,
408 	SHMIF_MIGRATE_TRANSFER_FAIL = -4,
409 	SHMIF_MIGRATE_BAD_SOURCE = -8
410 };
411 
412 enum shmif_migrate_status arcan_shmif_migrate(
413 	struct arcan_shmif_cont* cont, const char* newpath, const char* key);
414 
415 /*
416  * Using a identification string (implementation defined connection
417  * mechanism) If type is set to 0, no REGISTER event will be sent and
418  * you will need to send one manually.
419  */
420 struct arcan_shmif_cont arcan_shmif_acquire(
421 	struct arcan_shmif_cont* parent, /* should only be NULL internally */
422 	const char* shmkey,    /* provided in ENV or from shmif_connect below */
423 	int type, /* (enum ARCAN_SEGID) archetype, in shmif_event.h */
424 	int flags, /* (enum ARCAN_FLAGS) */
425 	...
426 );
427 
428 /*
429  * Used internally by _control etc. but also in ARCAN for mapping the
430  * different buffer positions / pointers, very limited use outside those
431  * contexts. Returns size: (end of last buffer) - addr
432  */
433 uintptr_t arcan_shmif_mapav(
434 	struct arcan_shmif_page* addr,
435 	shmif_pixel* vbuf[], size_t vbufc, size_t vbuf_sz,
436 	shmif_asample* abuf[], size_t abufc, size_t abuf_sz
437 );
438 
439 /*
440  * Calculate the actual size of the video buffer based on the set of hints and
441  * meta substructure. This is used INTERNALLY on both sides of SHMIF to
442  * calculate actual shmpage dimensions. The client can access this information
443  * as part of the shmif_cont structure.
444  */
445 size_t arcan_shmif_vbufsz(
446 	int meta, uint8_t hints, size_t w, size_t h, size_t rows, size_t cols);
447 
448 /*
449  * There can be one "post-flag, pre-semaphore" hook that will occur
450  * before triggering a sigmask and can be used to synch audio to video
451  * or video to audio during transfers.
452  * 'mask' argument defines the signal mask slot (A xor B only, A or B is
453  * undefined behavior).
454  */
455 shmif_trigger_hook arcan_shmif_signalhook(struct arcan_shmif_cont*,
456 	enum arcan_shmif_sigmask mask, shmif_trigger_hook, void* data);
457 
458 /*
459  * Using the specified shmpage state, synchronization semaphore handle,
460  * construct two event-queue contexts. Parent- flag should be set
461  * to false for frameservers
462  */
463 void arcan_shmif_setevqs(struct arcan_shmif_page*,
464 	sem_handle, arcan_evctx* inevq, arcan_evctx* outevq, bool parent);
465 
466 /* resize/synchronization protocol to issue a resize of the output video buffer.
467  *
468  * This request can be declined (false return value) and should be considered
469  * expensive (may block indefinitely). Anything that depends on the contents of
470  * the shared-memory dependent parts of shmif_cont (eventqueue, vidp/audp, ...)
471  * should be considered invalid during/after a call to shmif_resize and the
472  * function will internally rebuild these structures.
473  *
474  * THIS FUNCTION IS NOT THREAD SAFE -- While a resize is pending, none of the
475  * other operations (drop, signal, en/de- queue) are safe. If events are
476  * managed on a separate thread, these should be treated in mutual exclusion
477  * with the size operation. This means that the pointers in the shmcont may be
478  * relocated, so keeping around aliases are dangerous. This can be tricky in a
479  * common case with multiple producer threads (a, v) and another event thread
480  * that reacts with a resize upon an event.
481  *
482  * arcan_shmif_lock/unlock can be used as a convenience non-reentrant mutex.
483  *
484  * There are four possible outcomes here:
485  * a. resize fails, dimensions exceed hard-coded limits.
486  * b. resize succeeds, vidp/audp are re-aligned.
487  * c. resize succeeds, the segment is truncated to a new size.
488  * d. resize succeeds, we switch to a new shared memory connection.
489  *
490  * Note that the actual effects / resize behavior in the running appl may be
491  * delayed until the first shmif_signal call on the resized segment. This is
492  * done in order to avoid visual artifacts that would stem from having source
493  * material in one resolution while metadata refers to another.
494  */
495 bool arcan_shmif_resize(
496 	struct arcan_shmif_cont*, unsigned width, unsigned height);
497 
498 /*
499  * Extended version of resize that supports requesting more audio / video
500  * buffers for better swap/synch control. abuf_cnt and vbuf_cnt are limited
501  * to the constants ARCAN_SHMIF_
502  *
503  * [meta] is used for extended / privileged data transfered and is specified
504  * as a bitmask of the following flags:
505  */
506 enum shmif_ext_meta {
507 	SHMIF_META_NONE = 0,
508 
509 /*
510  * apad/apad_type region is reserved for extended color management, with
511  * normal SHMIF_SIGVID operation synchronizing updates, server side updating
512  * the structure with valid values, and client modifying
513  */
514 	SHMIF_META_CM = 2,
515 
516 /*
517  * The video buffers will be switched to represent a 16-bit Float(
518  * R16,G16,B16,A16) format for HDR content and tone-mapping or HDR output
519  * is expected of the arcan instance.
520  */
521 	SHMIF_META_HDRF16 = 4,
522 
523 /*
524  * This is reserved and not completely fleshed out yet,
525  * but will switch the semantics of the video buffer area to represent a
526  * texture-maps + GPU friendly packing format - with the apad area to
527  * define metadata.
528  */
529 	SHMIF_META_VOBJ = 8,
530 
531 /*
532  * This contains the meta for one complete avatar tracking + display
533  * The common case for this is for a tool like the hmdserver to provide
534  * data.
535  */
536 	SHMIF_META_VR = 16,
537 
538 /*
539  * Similar to HDR16, but switch to half-size mode (R8G8B8A8 -> RGB565)
540  */
541 	SHMIF_META_LDEF = 32,
542 
543 /*
544  * Similar to HDR16, LDEF - but the video buffer is interpreted as a
545  * compressed video frame. This is primarily to let cliens that have
546  * a valid h264, av1, ... stream forward this without decoding.
547  */
548 	SHMIF_META_VENC = 64
549 };
550 
551 /*
552  * The acknowledged mask is reflected in cont->adata, and may subsequently
553  * affect apad and apad_type in the addr-> substructure as well.
554  */
555 struct shmif_resize_ext {
556 	uint32_t meta;
557 
558 /* abuf_sz * abuf_cnt played back over samplerate */
559 	size_t abuf_sz;
560 	ssize_t abuf_cnt;
561 	ssize_t samplerate;
562 
563 	ssize_t vbuf_cnt;
564 /*
565  * this is only used with tpack, which gives us the relationship
566  * rows * cell_w = px_w
567  * cols * cell_h = px_h
568  */
569 	size_t rows;
570 	size_t cols;
571 
572 /* the number of ops (primitives) and ops-type come from shmif_sub and
573  * is used for calculating the size of the apad region reserved for vobj */
574 	size_t nops;
575 	size_t op_fm;
576 };
577 
578 /* extended resize that allows better buffering and format controls,
579  * WARNING, the abuf_cnt and vbuf_cnt are especially important as it is
580  * allowed to set them to 0 (disable audio or video respectively). To
581  * set to -1 means 'retain the last buffer size'
582  */
583 bool arcan_shmif_resize_ext(struct arcan_shmif_cont*,
584 	unsigned width, unsigned height, struct shmif_resize_ext);
585 
586 /*
587  * Unmap memory, release semaphores and related resources
588  */
589 void arcan_shmif_drop(struct arcan_shmif_cont*);
590 
591 /*
592  * Signal that a synchronized transfer should take place. The contents of the
593  * mask determine buffers to synch and blocking behavior.
594  *
595  * Returns the number of miliseconds that the synchronization reported, and
596  * is a value that can be used to adjust local rendering/buffer.
597  */
598 unsigned arcan_shmif_signal(struct arcan_shmif_cont*, enum arcan_shmif_sigmask);
599 
600 /*
601  * Signal a video transfer that is based on buffer sharing rather than on data
602  * in the shmpage. Otherwise it behaves like [arcan_shmif_signal] but with a
603  * possible reserved variadic argument for future use.
604  *
605  * If included with DEFINED(WANT_ARCAN_SHMIF_HELPER) and linked with
606  * arcan_shmif_ext, abstract support functions for setup and passing are
607  * provided (arcan_shmifext_***)
608  *
609  * mask matches (enum arcan_shmif_sigmask) but can't enforce the type here
610  * because of VA_ARGS + enum with -fshort-enums can yield UB.
611  *
612  * [NOTE]
613  * Ideally, this should work the other way around, i.e. on a resize, the server
614  * side provides the buffer descriptors to use, and signalhandle simply steps
615  * within this set.
616  * For DMA-Buf this is basically a no-go, while as for EGLStreams, that way
617  * would work better.
618  */
619 unsigned arcan_shmif_signalhandle(struct arcan_shmif_cont* ctx,
620 	int mask, int handle, size_t stride, int format, ...);
621 
622 /*
623  * Returns true of handle based buffer passing is permitted or not, if not
624  * a software based approach is required. The extended graphics mode of shmif
625  * performs this conversion automatically for most cases.
626  *
627  * This should be tested before attempting a signal-handle as the event that
628  * carries rejection asynchronously.
629  */
630 bool arcan_shmif_handle_permitted(struct arcan_shmif_cont* ctx);
631 
632 /*
633  * Support function to set/unset the primary access segment (one slot for
634  * input. one slot for output), manually managed. This is just a static member
635  * helper with no currently strongly negotiated meaning.
636  */
637 struct arcan_shmif_cont* arcan_shmif_primary(enum arcan_shmif_type);
638 void arcan_shmif_setprimary( enum arcan_shmif_type, struct arcan_shmif_cont*);
639 
640 /*
641  * Enable/Lock a mutex tied to the segment. This is primarily to protect when
642  * the segment is accessed in separate threads and you need to run a resize
643  * negotiation.
644  */
645 bool arcan_shmif_lock(struct arcan_shmif_cont*);
646 bool arcan_shmif_unlock(struct arcan_shmif_cont*);
647 
648 /*
649  * Update the failure callback associated with a context- remapping due to
650  * a connection failure. Although ->vidp and ->audp may be correct, there are
651  * no guarantees and any aliases to these buffers should be updated in the
652  * callback.
653  *
654  * This is mainly useful for cases where the same shmif context is shared
655  * across multiple threads, e.g. when there is an audio producer thread and
656  * a video producer thread.
657  *
658  * The pitfalls are tied to automatic migration from crash recovery, where one
659  * producer can be stuck in signalling a data transfer, and another in event
660  * dispatch.
661  *
662  * The event dispatch discovers a forced migration, which will cause the
663  * segment mappings to be dropped, which will first lock the context. If this
664  * happens while one of the producers is holding a lock, we would enter a
665  * deadlock state.
666  *
667  * The reset callback can be triggered in multiple states:
668  *
669  *   0 : in event handler / resized
670  *   1 : context is lost and will be remapped (multiple calls)
671  *   2 : context have been remapped
672  *   3 : context didn't need to be remapped
673  *   4 : context recovery failed / broken
674  *
675  * The function returns any previous reset hook defined on the context.
676  */
677 enum shmif_reset_hook {
678 	SHMIF_RESET_RESIZE  = 0,
679 	SHMIF_RESET_LOST    = 1,
680 	SHMIF_RESET_REMAP   = 2,
681 	SHMIF_RESET_NOCHG   = 3,
682 	SHMIF_RESET_FAIL    = 4
683 };
684 shmif_reset_hook arcan_shmif_resetfunc(
685 	struct arcan_shmif_cont*, shmif_reset_hook, void* tag);
686 
687 /*
688  * This should be called periodically to prevent more subtle bugs from
689  * cascading and be caught at an earlier stage, it checks the shared memory
690  * context against a series of cookies and known guard values, returning
691  * [false] if not everything checks out.
692  *
693  * The guard thread (if active) uses this function as part of its monitoring
694  * heuristic.
695  */
696 bool arcan_shmif_integrity_check(struct arcan_shmif_cont*);
697 
698 /*
699  * Check if audio and/or video buffers are pending or free,
700  *-1 : broken segment
701  * 0 : both are free
702  * 1 : video pending
703  * 2 : audio pending
704  * 3 : video and audio pending
705  */
706 int arcan_shmif_signalstatus(struct arcan_shmif_cont*);
707 
708 struct arcan_shmif_region {
709 	uint16_t x1, x2, y1, y2;
710 };
711 
712 struct arcan_shmif_cont {
713 	struct arcan_shmif_page* addr;
714 
715 /* offset- pointers into addr, can change between calls to shmif_ functions so
716  * aliasing is not recommended, especially important if (default)
717  * connection-crash recovery-reconnect is enabled as the address >may< be
718  * changed. If that is a concern, define a handler using the shmif_resetfunc */
719   union {
720 		shmif_pixel* vidp;
721 		float* floatp;
722 		uint8_t* vidb;
723 	};
724 	union {
725 		shmif_asample* audp;
726 		uint8_t* audb;
727 	};
728 
729 /*
730  * This cookie is set/kept to some implementation defined value and will be
731  * verified during integrity_check. It is placed here to quickly detect
732  * overflows in video or audio management from client side programming errors
733  */
734 	int16_t oflow_cookie;
735 
736 /* use EITHER [audp, abufpos, abufcount] OR [audb, abufused, abufsize]
737  * to populate the current audio buffer depending on if you are working on
738  * SAMPLES or BYTES. abufpos != 0 will assume the latter */
739 	uint16_t abufused, abufpos;
740 	uint16_t abufsize, abufcount;
741 
742 /* updated on resize, provided to get feedback on an extended resize */
743 	uint8_t abuf_cnt;
744 
745 /*
746  * the event handle is provided and used for signal event delivery
747  * in order to allow multiplexation with other input/output sources
748  */
749 	file_handle epipe;
750 
751 /*
752  * Maintain a connection to the shared memory handle in order to handle
753  * resizing (on platforms that support it, otherwise define
754  * ARCAN_SHMIF_OVERCOMMIT which will only recalc pointers on resize
755  */
756 	file_handle shmh;
757 	size_t shmsize;
758 
759 /*
760  * Used internally for synchronization (and mapped / managed outside
761  * the regular shmpage). system-defined but typically named semaphores.
762  */
763 	sem_handle vsem, asem, esem;
764 
765 /*
766  * Should be used to index vidp, i.e. vidp[y * pitch + x] = RGBA(r, g, b, a)
767  * stride and pitch account for padding, with stride being a row length in
768  * bytes and pitch a row length in pixels.
769  */
770 	size_t w, h, stride, pitch;
771 
772 /*
773  * acknowledged extended attributes in response to an shmif_resize_ext
774  * request. Affects addr->apad and addr->apad_type as well.
775  *
776  * Read only, SYNCH ON EXT_RESIZE
777  */
778 	uint32_t adata;
779 
780 /*
781  * defaults to ARCAN_SHMIF_SAMPLERATE but may be renegotiated as part
782  * of an extended resize. A deviation between the constant samplerate
783  * and the negotiated one will likely lead to resampling server-side.
784  *
785  * Read only, SYNCH ON EXT_RESIZE
786  */
787 	size_t samplerate;
788 
789 /*
790  * Presentation and buffer content / format hints:
791  *
792  * SHMIF_RHINT_ORIGO_UL (or LL),
793  * SHMIF_RHINT_IGNORE_ALPHA
794  * SHMIF_RHINT_SUBREGION (only synch dirty region below)
795  * SHMIF_RHINT_SUBREGION_CHAIN (reserved, not in use)
796  * SHMIF_RHINT_CSPACE_SRGB (non-linear color space)
797  * SHMIF_RHINT_AUTH_TOK
798  * SHMIF_RHINT_VSIGNAL_EV (get frame- delivery notification via STEPFRAME)
799  * SHMIF_RHINT_TPACK (video buffer contents is packed in TPACK format)
800  *
801  * Write only, SYNCH on shmif_resize() calls.
802  */
803 	uint8_t hints;
804 
805 /*
806  * IF the constraints:
807  *
808  * [Hints & SHMIF_RHINT_SUBREGION] and (X2>X1,(X2-X1)<=W,Y2>Y1,(Y2-Y1<=H))
809  * valid, [ARCAN] MAY synch only the specified region.
810  * Caller manipulates this field, will be copied to shmpage during synch.
811  *
812  * The [dx, dy] hints inside of the region indicates the number of pixels that
813  * are scrolled based on the previously synched buffer.
814  *
815  * The dirty region is reset on either calls to arcan_shmif_signal (video)
816  * or on shmif_resize calls that impose a size change.
817  */
818   struct arcan_shmif_region dirty;
819 
820 /*
821  * The cookie act as overflow monitor and trigger for ABI incompatibilities
822  * between arcan main and program using the shmif library. Combined from
823  * shmpage struct offsets and type sizes. Periodically monitored (using
824  * arcan_shmif_integrity_check calls) and incompatibilities is a terminal
825  * state transition.
826  */
827 	uint64_t cookie;
828 
829 /*
830  * User-tag, primarily to support attaching ancilliary data to subsegments
831  * that are run and synchronized in separate threads.
832  */
833 	void* user;
834 
835 /*
836  * Opaque struct for implementation defined tracking (guard thread handles
837  * and related data).
838  */
839 	struct shmif_hidden* priv;
840 	struct shmif_ext_hidden* privext;
841 
842 /*
843  * Copy of the segment token identifier provided on the shmpage at setup
844  */
845 	uint32_t segment_token;
846 
847 /*
848  * Video buffers may, based on extended contents hints etc. have a size
849  * that does not match the normal formula of w * h * pitch bytes. Instead,
850  * and length validation for user-side programming is best done against
851  * this field. This represents the size of a single video buffer.
852  */
853 	size_t vbufsize;
854 };
855 
856 struct arcan_shmif_initial {
857 /* pre-configured primary font and possible fallback, remember to convert
858  * to point size to account for density (interop macro
859  * SHMIF_PT_SIZE(ppcm, sz_mm) */
860 	struct {
861 		int fd;
862 		int type;
863 		int hinting;
864 		float size_mm;
865 	} fonts[4];
866 
867 /* output display density and LED- layout hint for subpixel hinting */
868 	float density;
869 	int rgb_layout;
870 
871 /* maximum display output dimensions */
872 	size_t display_width_px;
873 	size_t display_height_px;
874 	uint16_t rate;
875 
876 	uint8_t lang[4], country[4], text_lang[4];
877 	float latitude, longitude, elevation;
878 
879 /* device to use for 3D acceleration */
880 	int render_node;
881 
882 /* UTC + */
883 	int timezone;
884 
885 /* 16+16 possible color slots
886  *
887  *  [0,1] are reserved
888  *  2..14: primary, secondary, bg, text, cursor, altcursor, highlight, label,
889  *         warning, error, alert, reference, inactive, ui
890  *
891  *   15..: segment specific reference (terminal)
892  */
893 	struct {
894 		uint8_t fg[3];
895 		uint8_t bg[3];
896 		bool fg_set, bg_set;
897 	} colors[36];
898 
899 /* pixel size for cell alignment, this is mainly intended for TUI clients
900  * but could also be useful for grid- based UI components in toolkits that
901  * support such controls (CAD/CAM) */
902 	size_t cell_w;
903 	size_t cell_h;
904 };
905 
906 enum rhint_mask {
907 /*
908  * Indicate if the buffer is to be treated as having its y=0 in the upper-
909  * left corner of an imaginary screen, or in the lower-left. The default is
910  * upper left, but many 3D accelerated drawing systems use the other form.
911  */
912 	SHMIF_RHINT_ORIGO_UL = 0,
913 	SHMIF_RHINT_ORIGO_LL = 1,
914 
915 /*
916  * Indicate that only a smaller portion of the buffer actually needs to
917  * be updated. It is still up to the server to decide what will actually
918  * be synched however, as it may not have access to a cached backing store
919  * in which to blit the subregion.
920  */
921 	SHMIF_RHINT_SUBREGION = 2,
922 
923 /*
924  * Indicate that the contents of the alpha channel must be ignored or the
925  * output will not look as inteded. This is typical when the data source
926  * comes from a context that leaves the alpha channel in a 0- state and
927  * the client do not want to waste cycles repacking.
928  */
929 	SHMIF_RHINT_IGNORE_ALPHA = 4,
930 
931 /*
932  * For shmif- vidp transfers, the source color space defaults to linear-RGB.
933  *
934  * Setting this flag indicates that the source colorspace is in sRGB format
935  * and that the engine should pick shaders and blending algorithms that can
936  * take this non-linearity into account.
937  */
938 	SHMIF_RHINT_CSPACE_SRGB = 8,
939 
940 /*
941  * Used internally with shmifext_setup for the cases where we need to
942  * authenticate against the rendering subsystem. This is a no-op on many
943  * platforms. (ab)uses the VPTS field to exchange cookies.
944  */
945 	SHMIF_RHINT_AUTH_TOK = 16,
946 
947 /*
948  * Used for cases where it is not wise to block on the signal- semaphore.
949  * When the buffer contents have been consumed and can be modified without
950  * risking tearing or corruption, receive a STEPFRAME event. The STEPFRAME
951  * event will contain .iv[0] == 1, .iv[1] == 0.
952  * This increases the load on the incoming eventqueue, so should be avoided if
953  * possible. If the incoming eventqueue is closing in on becoming saturated,
954  * the STEPFRAME event will not be emitted.
955  */
956 	SHMIF_RHINT_VSIGNAL_EV = 32,
957 
958 /*
959  * [Reserved, not yet used]
960  * Change the buffer contents management method to be a chain of dirty
961  * rectangles rather than one continous buffer. This means that the contents of
962  * the normal vidp, stride and pitch members may mutate between calls to
963  * arcan_shmif_dirty and that it is write only, you can't use it for reliable
964  * blending etc. Setting this bit will invalidate SHMIF_RHINT_SUBREGION.
965  */
966 	SHMIF_RHINT_SUBREGION_CHAIN = 64,
967 
968 /*
969  * Changes the buffer contents to be packed in the TPACK format (see
970  * tui/raster). This means that the server side will ignore the normal size
971  * hints and emit window resizes etc. accordingly. Thus, _resize calls on
972  * a TPACK segment only needs to be called if the context vbufsize member
973  * is too small. In those cases, the _resize dimensions are still expected
974  * to be in pixels.
975  */
976 	SHMIF_RHINT_TPACK = 128
977 };
978 
979 struct arcan_shmif_page;
980 
981 #ifndef ARCAN_SHMIF_HIDEPAGE
982 struct arcan_shmif_page {
983 /*
984  * These will be statically set to the ASHMIF_VERSION_MAJOR, ASHMIF_VERSION_MAJOR
985  * defines, a mismatch will cause the integrity_check to fail and both sides
986  * may decide to terminate. Thus, they also act as a header guard. A more
987  * precise guard value is found in [cookie].
988  */
989 	int8_t major;
990 	int8_t minor;
991 
992 /* [FSRV-REQ, ARCAN-ACK, ATOMIC-NOCARE]
993  * Will be checked periodically and before transfers. When set, FSRV should
994  * treat other contents of page as UNDEFINED until acknowledged.
995  * RELATES-TO: width, height */
996 	 volatile int8_t resized;
997 
998 /* [FSRV-SET or ARCAN-SET, ATOMIC-NOCARE]
999  * Dead man's switch, set to 1 when a connection is active and released
1000  * if parent or child detects an anomaly that would indicate misuse or
1001  * data corruption. This will trigger guard-threads and similar structures
1002  * to release semaphores and attempt to shut down gracefully.
1003  */
1004 	volatile uint8_t dms;
1005 
1006 /* [FSRV-SET, ARCAN-ACK(fl+sem)]
1007  * Set whenever a buffer is ready to be synchronized.
1008  * [vready-1] indicates the buffer index of the last set frame, while
1009  * vpending are the number of frames with contents that hasn't been
1010  * synchronzied.
1011  * [aready-1] indicates the starting index for buffers that have not
1012  * been synchronized, ring-buffer wrapping the bits that are set.
1013  */
1014 	volatile atomic_uint aready;
1015 	volatile atomic_uint apending;
1016 	volatile atomic_uint vready;
1017 	volatile atomic_uint vpending;
1018 
1019 /* abufused contains the number of bytes consumed in every slot */
1020 	volatile _Atomic uint_least16_t abufused[ARCAN_SHMIF_ABUFC_LIM];
1021 
1022 /*
1023  * Presentation hints, manipulate field in _cont, not here.
1024  */
1025 	volatile _Atomic uint_least8_t hints;
1026 
1027 /*
1028  * see dirty- field in _cont, manipulate there, not here.
1029  */
1030 	volatile _Atomic struct arcan_shmif_region dirty;
1031 	volatile _Atomic int16_t scroll_dx;
1032 	volatile _Atomic int16_t scroll_dy;
1033 
1034 /* [FSRV-SET]
1035  * Unique (or 0) segment identifier. Prvodes a local namespace for specifying
1036  * relative properties (e.g. VIEWPORT command from popups) between subsegments,
1037  * is always 0 for subsegments.
1038  */
1039 	uint32_t segment_token;
1040 
1041 /* [ARCAN-SET]
1042  * Calculated once when initializing segment, and verified periodically from
1043  * both [FSRV] and [ARCAN]. Any deviation MAY have the [dms] be pulled.
1044  */
1045 	uint64_t cookie;
1046 
1047 /*
1048  * [ARCAN-SET (parent), FSRV-SET (child)]
1049  * Uses the event model provded in shmif/arcan_event and tightly couples
1050  * structure / event layout which introduces a number of implementation defined
1051  * constraints, making this interface a poor choice for a protocol.
1052  */
1053 	struct {
1054 		struct arcan_event evqueue[ PP_QUEUE_SZ ];
1055 		uint8_t front, back;
1056 	} childevq, parentevq;
1057 
1058 /* [ARCAN-SET (parent), FSRV-CHECK]
1059  * Arcan mandates segment size, will only change during resize negotiation.
1060  * If this differs from the previous known size (tracked inside shmif_cont),
1061  * the segment should be remapped.
1062  *
1063  * Not all operations will lead to a change in segment_size, OVERCOMMIT
1064  * builds has its size fixed, and parent may heuristically determine if
1065  * a shrinking- operation is worth the overhead or not.
1066  */
1067 	volatile uint32_t segment_size;
1068 
1069 /*
1070  * [FSRV-SET (resize), ARCAN-ACK]
1071  * Current video output dimensions. If these deviate from the agreed upon
1072  * dimensions (i.e. change w,h and set the resized flag to !0) ARCAN will
1073  * simply ignore the data presented.
1074  */
1075 	volatile _Atomic uint_least16_t w, h;
1076 
1077 /*
1078  * [ARCAN-SET, FSRV-SET]
1079  * Client acknowledges this in resize requests where cell alignment /
1080  * dimensions are needed, undefined unless in TPACK hint state. This should
1081  * be a value that can be calculated from fonthint etc. but that is asynch.
1082  */
1083 	volatile _Atomic uint_least8_t rows, cols;
1084 
1085 /*
1086  * [FSRV-SET (aready signal), ARCAN-ACK]
1087  * Video buffers are planar transfers of a pre-determined size. Audio,
1088  * on the other hand, can be appended and consumed by the side that currently
1089  * holds the synch- semaphore. Note that if the transfered amount for each
1090  * synch is less than the negotiated abufsize, audio artifacts may be heard.
1091  */
1092 	volatile _Atomic uint_least16_t abufsize;
1093 
1094 /*
1095  * [FSRV-SET (resize), ARCAN-ACK]
1096  * Desired buffer samplerate, 0 maps back to ARCAN_SHMIF_SAMPLERATE that
1097  * should be tuned for the underlying audio system at build-time.
1098  */
1099 	volatile _Atomic uint_least32_t audiorate;
1100 
1101 /*
1102  * [FSRV-OR-ARCAN-SET]
1103  * Timestamp hint for presentation of a video frame (using synch-to-video)
1104  * Also used as negotiation for RHINT_TOKEN_AUTH used by shmifext_setup
1105  * internally.
1106  */
1107 	volatile _Atomic uint_least64_t vpts;
1108 
1109 /*
1110  * [ARCAN-SET]
1111  * Set during segment initalization, provides some identifier to determine
1112  * if the parent process is still alive (used internally by GUARDTHREAD).
1113  * Can also be updated in relation to a RESET event.
1114  */
1115 	process_handle parent;
1116 
1117 /*
1118  * [FSRV-OR-ARCAN-SET]
1119  * Possibly changed during an extended resize
1120  * Set once during initiaization, and will be zero/NULL for most connection.
1121  * The intended use is to provide a mechanism for further engine segmentation
1122  * and for more complex data sources. A prime example is the hmdsupport tool.
1123  */
1124 	volatile _Atomic uint32_t apad, apad_type;
1125 
1126 /*
1127  * [FSRV-SET-ON-DMS/EXIT]
1128  * Short user-readable utf8- message to indicate a possible reason for a
1129  * crash, failure or otherwise unexpected termination
1130  */
1131 	volatile char last_words[32];
1132 
1133 /*
1134  * Begin of apad/apad_type negotiated block. For the actual calculations here,
1135  * look inside engine/arcan_frameserver.c for setproto, and in platform for
1136  * the shmemop.c implementation.
1137  */
1138 	_Alignas(16) uintptr_t adata[];
1139 };
1140 #endif
1141 #endif
1142