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