The open source OpenXR runtime

ipc: implement plane detection device functions

Co-Authored-By: Christoph Haag <christoph.haag@collabora.com>
Co-Authored-By: Korcan Hussein <korcan.hussein@collabora.com>
Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2439>

authored by

Simon Zeni
Christoph Haag
Korcan Hussein
and committed by
Korcan Hussein
f4c1b671 0eb9fd5d

+403 -2
+2
src/xrt/ipc/client/ipc_client_device.c
··· 280 280 icd->base.body_tracking_supported = isdev->body_tracking_supported; 281 281 icd->base.force_feedback_supported = isdev->force_feedback_supported; 282 282 icd->base.stage_supported = isdev->stage_supported; 283 + icd->base.planes_supported = isdev->planes_supported; 284 + icd->base.plane_capability_flags = isdev->plane_capability_flags; 283 285 284 286 icd->base.device_type = isdev->device_type; 285 287 return &icd->base;
+158
src/xrt/ipc/client/ipc_client_hmd.c
··· 271 271 return available; 272 272 } 273 273 274 + static enum xrt_result 275 + ipc_client_hmd_begin_plane_detection_ext(struct xrt_device *xdev, 276 + const struct xrt_plane_detector_begin_info_ext *begin_info, 277 + uint64_t plane_detection_id, 278 + uint64_t *out_plane_detection_id) 279 + { 280 + ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 281 + 282 + ich->ipc_c->ism->plane_begin_info_ext = *begin_info; 283 + 284 + xrt_result_t r = ipc_call_device_begin_plane_detection_ext(ich->ipc_c, ich->device_id, plane_detection_id, 285 + out_plane_detection_id); 286 + if (r != XRT_SUCCESS) { 287 + IPC_ERROR(ich->ipc_c, "Error sending hmd_begin_plane_detection_ext!"); 288 + return r; 289 + } 290 + 291 + return XRT_SUCCESS; 292 + } 293 + 294 + static enum xrt_result 295 + ipc_client_hmd_destroy_plane_detection_ext(struct xrt_device *xdev, uint64_t plane_detection_id) 296 + { 297 + ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 298 + 299 + xrt_result_t r = ipc_call_device_destroy_plane_detection_ext(ich->ipc_c, ich->device_id, plane_detection_id); 300 + if (r != XRT_SUCCESS) { 301 + IPC_ERROR(ich->ipc_c, "Error sending destroy_plane_detection_ext!"); 302 + return r; 303 + } 304 + 305 + return XRT_SUCCESS; 306 + } 307 + 308 + /*! 309 + * Helper function for @ref xrt_device::get_plane_detection_state. 310 + * 311 + * @public @memberof xrt_device 312 + */ 313 + static inline enum xrt_result 314 + ipc_client_hmd_get_plane_detection_state_ext(struct xrt_device *xdev, 315 + uint64_t plane_detection_id, 316 + enum xrt_plane_detector_state_ext *out_state) 317 + { 318 + ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 319 + 320 + xrt_result_t r = 321 + ipc_call_device_get_plane_detection_state_ext(ich->ipc_c, ich->device_id, plane_detection_id, out_state); 322 + if (r != XRT_SUCCESS) { 323 + IPC_ERROR(ich->ipc_c, "Error sending get_plane_detection_state_ext!"); 324 + return r; 325 + } 326 + 327 + return XRT_SUCCESS; 328 + } 329 + 330 + /*! 331 + * Helper function for @ref xrt_device::get_plane_detections. 332 + * 333 + * @public @memberof xrt_device 334 + */ 335 + static inline enum xrt_result 336 + ipc_client_hmd_get_plane_detections_ext(struct xrt_device *xdev, 337 + uint64_t plane_detection_id, 338 + struct xrt_plane_detections_ext *out_detections) 339 + { 340 + ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 341 + struct ipc_connection *ipc_c = ich->ipc_c; 342 + 343 + ipc_client_connection_lock(ipc_c); 344 + 345 + xrt_result_t xret = ipc_send_device_get_plane_detections_ext_locked(ipc_c, ich->device_id, plane_detection_id); 346 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_send_device_get_plane_detections_ext_locked", out); 347 + 348 + // in this case, size == count 349 + uint32_t location_size = 0; 350 + uint32_t polygon_size = 0; 351 + uint32_t vertex_size = 0; 352 + 353 + xret = ipc_receive_device_get_plane_detections_ext_locked(ipc_c, &location_size, &polygon_size, &vertex_size); 354 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive_device_get_plane_detections_ext_locked", out); 355 + 356 + 357 + // With no locations, the service won't send anything else 358 + if (location_size < 1) { 359 + out_detections->location_count = 0; 360 + goto out; 361 + } 362 + 363 + // realloc arrays in out_detections if necessary, then receive contents 364 + 365 + out_detections->location_count = location_size; 366 + if (out_detections->location_size < location_size) { 367 + U_ARRAY_REALLOC_OR_FREE(out_detections->locations, struct xrt_plane_detector_location_ext, 368 + location_size); 369 + U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_info_start_index, uint32_t, location_size); 370 + out_detections->location_size = location_size; 371 + } 372 + 373 + if (out_detections->polygon_info_size < polygon_size) { 374 + U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_infos, struct xrt_plane_polygon_info_ext, polygon_size); 375 + out_detections->polygon_info_size = polygon_size; 376 + } 377 + 378 + if (out_detections->vertex_size < vertex_size) { 379 + U_ARRAY_REALLOC_OR_FREE(out_detections->vertices, struct xrt_vec2, vertex_size); 380 + out_detections->vertex_size = vertex_size; 381 + } 382 + 383 + if ((location_size > 0 && 384 + (out_detections->locations == NULL || out_detections->polygon_info_start_index == NULL)) || 385 + (polygon_size > 0 && out_detections->polygon_infos == NULL) || 386 + (vertex_size > 0 && out_detections->vertices == NULL)) { 387 + IPC_ERROR(ich->ipc_c, "Error allocating memory for plane detections!"); 388 + out_detections->location_size = 0; 389 + out_detections->polygon_info_size = 0; 390 + out_detections->vertex_size = 0; 391 + xret = XRT_ERROR_IPC_FAILURE; 392 + goto out; 393 + } 394 + 395 + if (location_size > 0) { 396 + // receive location_count * locations 397 + xret = ipc_receive(&ipc_c->imc, out_detections->locations, 398 + sizeof(struct xrt_plane_detector_location_ext) * location_size); 399 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(1)", out); 400 + 401 + // receive location_count * polygon_info_start_index 402 + xret = ipc_receive(&ipc_c->imc, out_detections->polygon_info_start_index, 403 + sizeof(uint32_t) * location_size); 404 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(2)", out); 405 + } 406 + 407 + 408 + if (polygon_size > 0) { 409 + // receive polygon_count * polygon_infos 410 + xret = ipc_receive(&ipc_c->imc, out_detections->polygon_infos, 411 + sizeof(struct xrt_plane_polygon_info_ext) * polygon_size); 412 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(3)", out); 413 + } 414 + 415 + if (vertex_size > 0) { 416 + // receive vertex_count * vertices 417 + xret = ipc_receive(&ipc_c->imc, out_detections->vertices, sizeof(struct xrt_vec2) * vertex_size); 418 + IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(4)", out); 419 + } 420 + 421 + out: 422 + ipc_client_connection_unlock(ipc_c); 423 + return xret; 424 + } 425 + 274 426 static xrt_result_t 275 427 ipc_client_hmd_get_visibility_mask(struct xrt_device *xdev, 276 428 enum xrt_visibility_mask_type type, ··· 332 484 ich->base.get_face_tracking = ipc_client_hmd_get_face_tracking; 333 485 ich->base.get_view_poses = ipc_client_hmd_get_view_poses; 334 486 ich->base.compute_distortion = ipc_client_hmd_compute_distortion; 487 + ich->base.begin_plane_detection_ext = ipc_client_hmd_begin_plane_detection_ext; 488 + ich->base.destroy_plane_detection_ext = ipc_client_hmd_destroy_plane_detection_ext; 489 + ich->base.get_plane_detection_state_ext = ipc_client_hmd_get_plane_detection_state_ext; 490 + ich->base.get_plane_detections_ext = ipc_client_hmd_get_plane_detections_ext; 335 491 ich->base.destroy = ipc_client_hmd_destroy; 336 492 ich->base.is_form_factor_available = ipc_client_hmd_is_form_factor_available; 337 493 ich->base.get_visibility_mask = ipc_client_hmd_get_visibility_mask; ··· 396 552 ich->base.form_factor_check_supported = isdev->form_factor_check_supported; 397 553 ich->base.stage_supported = isdev->stage_supported; 398 554 ich->base.battery_status_supported = isdev->battery_status_supported; 555 + ich->base.planes_supported = isdev->planes_supported; 556 + ich->base.plane_capability_flags = isdev->plane_capability_flags; 399 557 400 558 return &ich->base; 401 559 }
+10
src/xrt/ipc/server/ipc_server.h
··· 140 140 141 141 struct ipc_app_state client_state; 142 142 143 + 144 + uint64_t plane_detection_size; 145 + uint64_t plane_detection_count; 146 + 147 + //! Array of plane detection ids with plane_detection_size entries. 148 + uint64_t *plane_detection_ids; 149 + 150 + //! Array of xrt_devices with plane_detection_size entries. 151 + struct xrt_device **plane_detection_xdev; 152 + 143 153 int server_thread_index; 144 154 }; 145 155
+170
src/xrt/ipc/server/ipc_server_handler.c
··· 2081 2081 } 2082 2082 2083 2083 xrt_result_t 2084 + ipc_handle_device_begin_plane_detection_ext(volatile struct ipc_client_state *ics, 2085 + uint32_t id, 2086 + uint64_t plane_detection_id, 2087 + uint64_t *out_plane_detection_id) 2088 + { 2089 + // To make the code a bit more readable. 2090 + uint32_t device_id = id; 2091 + struct xrt_device *xdev = get_xdev(ics, device_id); 2092 + 2093 + uint64_t new_count = ics->plane_detection_count + 1; 2094 + 2095 + if (new_count > ics->plane_detection_size) { 2096 + IPC_TRACE(ics->server, "Plane detections tracking size: %u -> %u", (uint32_t)ics->plane_detection_count, 2097 + (uint32_t)new_count); 2098 + 2099 + U_ARRAY_REALLOC_OR_FREE(ics->plane_detection_ids, uint64_t, new_count); 2100 + U_ARRAY_REALLOC_OR_FREE(ics->plane_detection_xdev, struct xrt_device *, new_count); 2101 + ics->plane_detection_size = new_count; 2102 + } 2103 + 2104 + struct xrt_plane_detector_begin_info_ext *begin_info = &ics->server->ism->plane_begin_info_ext; 2105 + 2106 + enum xrt_result xret = 2107 + xrt_device_begin_plane_detection_ext(xdev, begin_info, plane_detection_id, out_plane_detection_id); 2108 + if (xret != XRT_SUCCESS) { 2109 + IPC_TRACE(ics->server, "xrt_device_begin_plane_detection_ext error: %d", xret); 2110 + return xret; 2111 + } 2112 + 2113 + if (*out_plane_detection_id != 0) { 2114 + uint64_t index = ics->plane_detection_count; 2115 + ics->plane_detection_ids[index] = *out_plane_detection_id; 2116 + ics->plane_detection_xdev[index] = xdev; 2117 + ics->plane_detection_count = new_count; 2118 + } 2119 + 2120 + return XRT_SUCCESS; 2121 + } 2122 + 2123 + xrt_result_t 2124 + ipc_handle_device_destroy_plane_detection_ext(volatile struct ipc_client_state *ics, 2125 + uint32_t id, 2126 + uint64_t plane_detection_id) 2127 + { 2128 + // To make the code a bit more readable. 2129 + uint32_t device_id = id; 2130 + struct xrt_device *xdev = get_xdev(ics, device_id); 2131 + 2132 + enum xrt_result xret = xrt_device_destroy_plane_detection_ext(xdev, plane_detection_id); 2133 + 2134 + // Iterate through plane detection ids. Once found, move every item one slot to the left. 2135 + bool compact_right = false; 2136 + for (uint32_t i = 0; i < ics->plane_detection_count; i++) { 2137 + if (ics->plane_detection_ids[i] == plane_detection_id) { 2138 + compact_right = true; 2139 + } 2140 + if (compact_right && (i + 1) < ics->plane_detection_count) { 2141 + ics->plane_detection_ids[i] = ics->plane_detection_ids[i + 1]; 2142 + ics->plane_detection_xdev[i] = ics->plane_detection_xdev[i + 1]; 2143 + } 2144 + } 2145 + // if the plane detection was correctly tracked compact_right should always be true 2146 + if (compact_right) { 2147 + ics->plane_detection_count -= 1; 2148 + } else { 2149 + IPC_ERROR(ics->server, "Destroyed plane detection that was not tracked"); 2150 + } 2151 + 2152 + if (xret != XRT_SUCCESS) { 2153 + IPC_ERROR(ics->server, "xrt_device_destroy_plane_detection_ext error: %d", xret); 2154 + return xret; 2155 + } 2156 + 2157 + return XRT_SUCCESS; 2158 + } 2159 + 2160 + xrt_result_t 2161 + ipc_handle_device_get_plane_detection_state_ext(volatile struct ipc_client_state *ics, 2162 + uint32_t id, 2163 + uint64_t plane_detection_id, 2164 + enum xrt_plane_detector_state_ext *out_state) 2165 + { 2166 + // To make the code a bit more readable. 2167 + uint32_t device_id = id; 2168 + struct xrt_device *xdev = get_xdev(ics, device_id); 2169 + 2170 + xrt_result_t xret = xrt_device_get_plane_detection_state_ext(xdev, plane_detection_id, out_state); 2171 + if (xret != XRT_SUCCESS) { 2172 + IPC_ERROR(ics->server, "xrt_device_get_plane_detection_state_ext error: %d", xret); 2173 + return xret; 2174 + } 2175 + 2176 + return XRT_SUCCESS; 2177 + } 2178 + 2179 + xrt_result_t 2180 + ipc_handle_device_get_plane_detections_ext(volatile struct ipc_client_state *ics, 2181 + uint32_t id, 2182 + uint64_t plane_detection_id) 2183 + 2184 + { 2185 + struct ipc_message_channel *imc = (struct ipc_message_channel *)&ics->imc; 2186 + struct ipc_device_get_plane_detections_ext_reply reply = XRT_STRUCT_INIT; 2187 + struct ipc_server *s = ics->server; 2188 + 2189 + // To make the code a bit more readable. 2190 + uint32_t device_id = id; 2191 + struct xrt_device *xdev = get_xdev(ics, device_id); 2192 + 2193 + struct xrt_plane_detections_ext out = {0}; 2194 + 2195 + xrt_result_t xret = xrt_device_get_plane_detections_ext(xdev, plane_detection_id, &out); 2196 + if (xret != XRT_SUCCESS) { 2197 + IPC_ERROR(ics->server, "xrt_device_get_plane_detections_ext error: %d", xret); 2198 + // probably nothing allocated on error, but make sure 2199 + xrt_plane_detections_ext_clear(&out); 2200 + return xret; 2201 + } 2202 + 2203 + reply.result = XRT_SUCCESS; 2204 + reply.location_size = out.location_count; // because we initialized to 0, now size == count 2205 + reply.polygon_size = out.polygon_info_size; 2206 + reply.vertex_size = out.vertex_size; 2207 + 2208 + xret = ipc_send(imc, &reply, sizeof(reply)); 2209 + if (xret != XRT_SUCCESS) { 2210 + IPC_ERROR(s, "Failed to send reply!"); 2211 + goto out; 2212 + } 2213 + 2214 + // send expected contents 2215 + 2216 + if (out.location_count > 0) { 2217 + xret = 2218 + ipc_send(imc, out.locations, sizeof(struct xrt_plane_detector_location_ext) * out.location_count); 2219 + if (xret != XRT_SUCCESS) { 2220 + IPC_ERROR(s, "Failed to send locations!"); 2221 + goto out; 2222 + } 2223 + 2224 + xret = ipc_send(imc, out.polygon_info_start_index, sizeof(uint32_t) * out.location_count); 2225 + if (xret != XRT_SUCCESS) { 2226 + IPC_ERROR(s, "Failed to send locations!"); 2227 + goto out; 2228 + } 2229 + } 2230 + 2231 + if (out.polygon_info_size > 0) { 2232 + xret = 2233 + ipc_send(imc, out.polygon_infos, sizeof(struct xrt_plane_polygon_info_ext) * out.polygon_info_size); 2234 + if (xret != XRT_SUCCESS) { 2235 + IPC_ERROR(s, "Failed to send polygon_infos!"); 2236 + goto out; 2237 + } 2238 + } 2239 + 2240 + if (out.vertex_size > 0) { 2241 + xret = ipc_send(imc, out.vertices, sizeof(struct xrt_vec2) * out.vertex_size); 2242 + if (xret != XRT_SUCCESS) { 2243 + IPC_ERROR(s, "Failed to send vertices!"); 2244 + goto out; 2245 + } 2246 + } 2247 + 2248 + out: 2249 + xrt_plane_detections_ext_clear(&out); 2250 + return xret; 2251 + } 2252 + 2253 + xrt_result_t 2084 2254 ipc_handle_device_set_output(volatile struct ipc_client_state *ics, 2085 2255 uint32_t id, 2086 2256 enum xrt_output_name name,
+11
src/xrt/ipc/server/ipc_server_per_client_thread.c
··· 101 101 ics->device_feature_used[i] = false; 102 102 } 103 103 104 + // Make sure undestroyed plane detections are cleaned up 105 + for (uint32_t i = 0; i < ics->plane_detection_count; i++) { 106 + xrt_device_destroy_plane_detection_ext(ics->plane_detection_xdev[i], ics->plane_detection_ids[i]); 107 + } 108 + free(ics->plane_detection_ids); 109 + free(ics->plane_detection_xdev); 110 + ics->plane_detection_ids = NULL; 111 + ics->plane_detection_xdev = NULL; 112 + ics->plane_detection_size = 0; 113 + ics->plane_detection_count = 0; 114 + 104 115 // Should we stop the server when a client disconnects? 105 116 if (ics->server->exit_on_disconnect) { 106 117 ics->server->running = false;
+7
src/xrt/ipc/server/ipc_server_process.c
··· 356 356 isdev->body_tracking_supported = xdev->body_tracking_supported; 357 357 isdev->stage_supported = xdev->stage_supported; 358 358 isdev->battery_status_supported = xdev->battery_status_supported; 359 + isdev->planes_supported = xdev->planes_supported; 360 + isdev->plane_capability_flags = xdev->plane_capability_flags; 359 361 360 362 // Setup the tracking origin. 361 363 isdev->tracking_origin_index = (uint32_t)-1; ··· 964 966 ics->server = vs; 965 967 ics->server_thread_index = cs_index; 966 968 ics->io_active = true; 969 + 970 + ics->plane_detection_size = 0; 971 + ics->plane_detection_count = 0; 972 + ics->plane_detection_ids = NULL; 973 + ics->plane_detection_xdev = NULL; 967 974 968 975 os_thread_start(&it->thread, ipc_server_client_thread, (void *)ics); 969 976
+5 -2
src/xrt/ipc/shared/ipc_protocol.h
··· 145 145 bool form_factor_check_supported; 146 146 bool stage_supported; 147 147 bool battery_status_supported; 148 + bool planes_supported; 149 + enum xrt_plane_detection_capability_flags_ext plane_capability_flags; 148 150 }; 149 151 150 - static_assert(sizeof(struct ipc_shared_device) == 560, 152 + static_assert(sizeof(struct ipc_shared_device) == 564, 151 153 "invalid structure size, maybe different 32/64 bits sizes or padding"); 152 154 153 155 /*! ··· 296 298 struct ipc_layer_slot slots[IPC_MAX_SLOTS]; 297 299 298 300 uint64_t startup_timestamp; 301 + struct xrt_plane_detector_begin_info_ext plane_begin_info_ext; 299 302 }; 300 303 301 - static_assert(sizeof(struct ipc_shared_memory) == 6497680, 304 + static_assert(sizeof(struct ipc_shared_memory) == 6499920, 302 305 "invalid structure size, maybe different 32/64 bits sizes or padding"); 303 306 304 307 /*!
+40
src/xrt/ipc/shared/proto.json
··· 465 465 ] 466 466 }, 467 467 468 + "device_begin_plane_detection_ext": { 469 + "in": [ 470 + {"name": "id", "type": "uint32_t"}, 471 + {"name": "plane_detection_id", "type": "uint64_t"} 472 + ], 473 + "out": [ 474 + {"name": "out_plane_detection_id", "type": "uint64_t"} 475 + ] 476 + }, 477 + 478 + "device_destroy_plane_detection_ext": { 479 + "in": [ 480 + {"name": "id", "type": "uint32_t"}, 481 + {"name": "plane_detection_id", "type": "uint64_t"} 482 + ] 483 + }, 484 + 485 + "device_get_plane_detection_state_ext": { 486 + "in": [ 487 + {"name": "id", "type": "uint32_t"}, 488 + {"name": "plane_detection_id", "type": "uint64_t"} 489 + ], 490 + "out": [ 491 + {"name": "state", "type": "enum xrt_plane_detector_state_ext"} 492 + ] 493 + }, 494 + 495 + "device_get_plane_detections_ext": { 496 + "varlen": true, 497 + "in": [ 498 + {"name": "id", "type": "uint32_t"}, 499 + {"name": "plane_detection_id", "type": "uint64_t"} 500 + ], 501 + "out": [ 502 + {"name": "location_size", "type": "uint32_t"}, 503 + {"name": "polygon_size", "type": "uint32_t"}, 504 + {"name": "vertex_size", "type": "uint32_t"} 505 + ] 506 + }, 507 + 468 508 "device_set_output": { 469 509 "in": [ 470 510 {"name": "id", "type": "uint32_t"},