1 /*
2  Arcan Shared Memory Interface, Extended Mapping
3 
4  Friendly Warning:
5  These are extended internal sub-protocols only used for segmenting the
6  engine into multiple processes. It relies on data-types not defined in
7  the rest of shmif and is therefore wholly unsuitable for inclusion or
8  use in code elsewhere.
9  */
10 
11 /*
12  Copyright (c) 2016-2020, Bjorn Stahl
13  All rights reserved.
14 
15  Redistribution and use in source and binary forms,
16  with or without modification, are permitted provided that the
17  following conditions are met:
18 
19  1. Redistributions of source code must retain the above copyright notice,
20  this list of conditions and the following disclaimer.
21 
22  2. Redistributions in binary form must reproduce the above copyright notice,
23  this list of conditions and the following disclaimer in the documentation
24  and/or other materials provided with the distribution.
25 
26  3. Neither the name of the copyright holder nor the names of its contributors
27  may be used to endorse or promote products derived from this software without
28  specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
34  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
35  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
40  THE POSSIBILITY OF SUCH DAMAGE.
41 */
42 
43 #ifndef HAVE_ARCAN_SHMIF_SUBPROTO
44 #define HAVE_ARCAN_SHMIF_SUBPROTO
45 
46 /*
47  * BSD checksum, from BSD sum. We calculate this to get lock-free updates while
48  * staying away from atomic/reordering (since there's no atomic 64- byte type
49  * anyhow). The added gain is that when metadata is synched and we're in a
50  * partial update, the failed checksum means there is new data on the way
51  * anyhow or something more sinister is afoot.
52  */
subp_checksum(const uint8_t * const buf,size_t len)53 static inline uint16_t subp_checksum(const uint8_t* const buf, size_t len)
54 {
55 	uint16_t res = 0;
56 	for (size_t i = 0; i < len; i++){
57 		if (res & 1)
58 			res |= 0x10000;
59 		res = ((res >> 1) + buf[i]) & 0xffff;
60 	}
61 	return res;
62 }
63 
64 /*
65  * Forward declarations of the current sub- structures, and a union of
66  * the safe / known return pointers in order to avoid explicit casting
67  */
68 struct arcan_shmif_vr;
69 struct arcan_shmif_ramp;
70 struct arcan_shmif_hdr16f;
71 struct arcan_shmif_vector;
72 struct arcan_shmif_venc;
73 
74 union shmif_ext_substruct {
75 	struct arcan_shmif_vr* vr;
76 	struct arcan_shmif_ramp* cramp;
77 	struct arcan_shmif_hdr16f* hdr;
78 	struct arcan_shmif_vector* vector;
79 	struct arcan_shmif_venc* venc;
80 };
81 
82 /*
83  * Extract a valid sub-structure from the context. This should have been
84  * negotiated with an extended resize request in advance, and need to be
85  * re- extracted in the event of an extended meta renegotiation, a reset
86  * or a migration. The safest pattern is to simply call when the data is
87  * needed and never cache.
88  */
89 union shmif_ext_substruct arcan_shmif_substruct(
90 	struct arcan_shmif_cont* ctx, enum shmif_ext_meta meta);
91 
92 /*
93  * Marks the beginning of the offset table that is set if subprotocols
94  * have been activated. Used internally by the resize- function. The
95  * strict copy is kept server-side.
96  */
97 struct arcan_shmif_ofstbl {
98 	union {
99 	struct {
100 		uint32_t ofs_ramp, sz_ramp;
101 		uint32_t ofs_vr, sz_vr;
102 		uint32_t ofs_hdr, sz_hdr;
103 		uint32_t ofs_vector, sz_vector;
104 	};
105 	uint32_t offsets[32];
106 	};
107 };
108 
109 struct arcan_shmif_hdr16f {
110 	int unused;
111 };
112 
113 /* verified during _signal, framesize <= w * h * sizeof(shmif_pixel) */
114 struct arcan_shmif_venc {
115 	uint8_t fourcc[4];
116 	size_t framesize;
117 };
118 
119 /*
120  * similar to how agp_mesh_store accepts data, the reordering would
121  * happen in the copy+validation stage. negative offset fields mean
122  * the data isn't present.
123  */
124 struct shmif_vector_mesh {
125 	int32_t ofs_verts; /* float */
126 	int32_t ofs_txcos; /* float */
127 	int32_t ofs_txcos2; /* float */
128 	int32_t ofs_normals; /* float */
129 	int32_t ofs_colors; /* float */
130 	int32_t ofs_tangents; /* float */
131 	int32_t ofs_bitangents; /* float */
132 	int32_t ofs_weights; /* float */
133 	int32_t ofs_joints; /* uint16 */
134 	int32_t ofs_indices; /* uint32 */
135 
136 	size_t vertex_size;
137 	size_t n_vertices;
138 	size_t n_indices;
139 	int primitive;
140 
141 	size_t buffer_sz;
142 	uint8_t* buffer;
143 };
144 
145 struct arcan_shmif_vector {
146 /* PRODUCER set */
147 	size_t data_sz;
148 	uint8_t mesh_groups;
149 	struct shmif_vector_mesh meshes[];
150 };
151 
152 /*
153  * Though it might seem that this information gets lost on a resize request,
154  * that is only true if the substructure set changes. Otherwise it's part of
155  * the base that gets copied over.
156  */
157 
158 /*
159  * the number of maximum crtcs/planes with support for lut- tables
160  */
161 #define SHMIF_CMRAMP_PLIM 4
162 #define SHMIF_CMRAMP_UPLIM 4095 /* % 3 == 0 */
163 
164 struct ramp_block {
165 	uint8_t format;
166 
167 /* checksum covers edid + plane-data */
168 	uint16_t checksum;
169 
170 	size_t plane_sizes[SHMIF_CMRAMP_PLIM];
171 
172 	uint8_t edid[128];
173 
174 /* set to indicate nominal resolution and refresh rate */
175 	size_t width, height;
176 	uint8_t vrate_int, vrate_fract;
177 
178 /* plane_sizes determines consumed size and mapping, color information
179  * can be retrieved from edid (assume RGB and let plane_sizes determine
180  * planar or interleaved if no edid). */
181 	float planes[SHMIF_CMRAMP_UPLIM];
182 };
183 
184 #define ARCAN_SHMIF_RAMPMAGIC 0xfafafa10
185 struct arcan_shmif_ramp {
186 	uint32_t magic;
187 
188 /* BITMASK, PRODUCER SET, CONSUMER CLEAR */
189 	_Atomic uint_least8_t dirty_in;
190 
191 /* BITMASK, CONSUMER SET, PRODUCER CLEAR */
192 	_Atomic uint_least8_t dirty_out;
193 
194 /* PRODUCER INIT, will be %2, first _in the _out */
195 	uint8_t n_blocks;
196 
197 /* PRODUCER INIT, CONSUMER_UPDATE */
198 	struct ramp_block ramps[];
199 };
200 
201 #define SHMIF_CMRAMP_RVA(X)(sizeof(struct ramp_block) * (X) *\
202 	SHMIF_CMRAMP_PLIM * SHMIF_CMRAMP_UPLIM)
203 
204 /*
205  * retrieve/flag-read the ramp at index [ind], and store a copy of
206  * its contents into [out] (if !NULL).
207  * Returns false if the index is out of bounds (SHMIF_CMRAMP_PLANE)
208  * or the contents failed checksum test.
209  */
210 bool arcan_shmifsub_getramp(
211 	struct arcan_shmif_cont* cont, size_t ind, struct ramp_block* out);
212 
213 /*
214  * update the ramp at index [ind] and mark as updated.
215  * returns false if the ramp couldn't be set (missing permissions or
216  * index out of bounds), true if it was successfully updated.
217  */
218 bool arcan_shmifsub_setramp(
219 	struct arcan_shmif_cont* cont, size_t ind, struct ramp_block* in);
220 
221 /*
222  * To avoid namespace collisions, the detailed VR structure relies
223  * on having access to the definitions in arcan_math.h from the core
224  * engine code.
225  */
226 #ifdef HAVE_ARCAN_MATH
227 #define VR_VERSION 0x1
228 
229 /*
230  * This structure is mapped into the adata area. It can be verified
231  * if the apad value match the size and the apad_type matches the
232  * SHMIF_APAD_VR constant.
233  */
234 enum avatar_limbs {
235 	PERSON = 1, /* abstract for global positioning */
236 	NECK,
237 	L_EYE,
238 	R_EYE,
239 	L_SHOULDER,
240 	R_SHOULDER,
241 	L_ELBOW,
242 	R_ELBOW,
243 	L_WRIST,
244 	R_WRIST,
245 /* might seem overly detailed but with glove- devices some points
246  * can be sampled and others can be inferred through kinematics */
247 	L_THUMB_PROXIMAL,
248 	L_THUMB_MIDDLE,
249 	L_THUMB_DISTAL,
250 	L_POINTER_PROXIMAL,
251 	L_POINTER_MIDDLE,
252 	L_POINTER_DISTAL,
253 	L_MIDDLE_PROXIMAL,
254 	L_MIDDLE_MIDDLE,
255 	L_MIDDLE_DISTAL,
256 	L_RING_PROXIMAL,
257 	L_RING_MIDDLE,
258 	L_RING_DISTAL,
259 	L_PINKY_PROXIMAL,
260 	L_PINKY_MIDDLE,
261 	L_PINKY_DISTAL,
262 	R_THUMB_PROXIMAL,
263 	R_THUMB_MIDDLE,
264 	R_THUMB_DISTAL,
265 	R_POINTER_PROXIMAL,
266 	R_POINTER_MIDDLE,
267 	R_POINTER_DISTAL,
268 	R_MIDDLE_PROXIMAL,
269 	R_MIDDLE_MIDDLE,
270 	R_MIDDLE_DISTAL,
271 	R_RING_PROXIMAL,
272 	R_RING_MIDDLE,
273 	R_RING_DISTAL,
274 	R_PINKY_PROXIMAL,
275 	R_PINKY_MIDDLE,
276 	R_PINKY_DISTAL,
277 	L_HIP,
278 	R_HIP,
279 	L_KNEE,
280 	R_KNEE,
281 	L_ANKLE,
282 	R_ANKLE,
283 	L_TOOL,
284 	R_TOOL,
285 	LIMB_LIM
286 };
287 
288 /*
289  * The standard lens parameters
290  */
291 struct vr_meta {
292 /* pixels */
293 	unsigned hres;
294 	unsigned vres;
295 
296 /* values in meters to keep < 1.0 */
297 	float h_size;
298 	float v_size;
299 	float h_center;
300 	float eye_display;
301 	float lens_distance;
302 	float ipd;
303 	float left_fov;
304 	float right_fov;
305 	float left_ar;
306 	float right_ar;
307 	float hsep;
308 	float vpos;
309 
310 /* correction constants */
311 	float distortion[4];
312 	float abberation[4];
313 
314 	float projection_left[16];
315 	float projection_right[16];
316 };
317 
318 union vr_data {
319 	uint8_t data[64];
320 	struct {
321 		vector position;
322 		vector forward;
323 		quat orientation;
324 		_Atomic uint16_t checksum;
325 	};
326 };
327 
328 struct vr_limb {
329 /* PRODUCER_SET (activation, or 0 if no haptics) */
330 	uint8_t haptic_id;
331 	uint8_t haptic_capabilities;
332 
333 /* CONSUMER-SET: don't bother updating, won't be used. */
334 	uint8_t ignored;
335 
336 /* PRODUCER_SET (activation) */
337 	uint8_t limb_type;
338 
339 /* PRODUCER_UPDATE */
340 	_Atomic uint_least32_t timestamp;
341 
342 /* PRODUCER UPDATE */
343 	union vr_data data;
344 };
345 
346 /*
347  * 0 <= (page_sz) - offset_of(limb) - limb_lim*sizeof(struct) limb
348  */
349 struct arcan_shmif_vr {
350 /* CONSUMER SET (activation) */
351 	uint8_t version;
352 	uint8_t limb_lim;
353 
354 /* PRODUCER MODIFY */
355 	_Atomic uint_least64_t limb_mask;
356 
357 /* PRODUCER SET/CONSUMER CLEAR */
358 	_Atomic uint_least8_t ready;
359 
360 /* PRODUCER INIT */
361 	struct vr_meta meta;
362 
363 /* PRODUCER UPDATE (see struct definition) */
364 	struct vr_limb limbs[];
365 };
366 #endif
367 #endif
368