diff --git a/src/xrt/compositor/client/comp_gl_client.c b/src/xrt/compositor/client/comp_gl_client.c index 3e01744c3..3c874adb2 100644 --- a/src/xrt/compositor/client/comp_gl_client.c +++ b/src/xrt/compositor/client/comp_gl_client.c @@ -262,6 +262,25 @@ client_gl_compositor_layer_cylinder(struct xrt_compositor *xc, return xrt_comp_layer_cylinder(&c->xcn->base, xdev, xscfb, &d); } +static xrt_result_t +client_gl_compositor_layer_equirect1(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data) +{ + struct client_gl_compositor *c = client_gl_compositor(xc); + struct xrt_swapchain *xscfb; + + assert(data->type == XRT_LAYER_EQUIRECT1); + + xscfb = &client_gl_swapchain(xsc)->xscn->base; + + struct xrt_layer_data d = *data; + d.flip_y = !d.flip_y; + + return xrt_comp_layer_equirect1(&c->xcn->base, xdev, xscfb, &d); +} + static xrt_result_t client_gl_compositor_layer_equirect2(struct xrt_compositor *xc, struct xrt_device *xdev, @@ -442,6 +461,7 @@ client_gl_compositor_init(struct client_gl_compositor *c, c->base.base.layer_quad = client_gl_compositor_layer_quad; c->base.base.layer_cube = client_gl_compositor_layer_cube; c->base.base.layer_cylinder = client_gl_compositor_layer_cylinder; + c->base.base.layer_equirect1 = client_gl_compositor_layer_equirect1; c->base.base.layer_equirect2 = client_gl_compositor_layer_equirect2; c->base.base.layer_commit = client_gl_compositor_layer_commit; c->base.base.destroy = client_gl_compositor_destroy; diff --git a/src/xrt/compositor/client/comp_vk_client.c b/src/xrt/compositor/client/comp_vk_client.c index f7d160336..c69b343fd 100644 --- a/src/xrt/compositor/client/comp_vk_client.c +++ b/src/xrt/compositor/client/comp_vk_client.c @@ -329,6 +329,22 @@ client_vk_compositor_layer_cylinder(struct xrt_compositor *xc, return xrt_comp_layer_cylinder(&c->xcn->base, xdev, xscfb, data); } +static xrt_result_t +client_vk_compositor_layer_equirect1(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data) +{ + struct client_vk_compositor *c = client_vk_compositor(xc); + struct xrt_swapchain *xscfb; + + assert(data->type == XRT_LAYER_EQUIRECT1); + + xscfb = &client_vk_swapchain(xsc)->xscn->base; + + return xrt_comp_layer_equirect1(&c->xcn->base, xdev, xscfb, data); +} + static xrt_result_t client_vk_compositor_layer_equirect2(struct xrt_compositor *xc, struct xrt_device *xdev, @@ -541,6 +557,7 @@ client_vk_compositor_create(struct xrt_compositor_native *xcn, c->base.base.layer_quad = client_vk_compositor_layer_quad; c->base.base.layer_cube = client_vk_compositor_layer_cube; c->base.base.layer_cylinder = client_vk_compositor_layer_cylinder; + c->base.base.layer_equirect1 = client_vk_compositor_layer_equirect1; c->base.base.layer_equirect2 = client_vk_compositor_layer_equirect2; c->base.base.layer_commit = client_vk_compositor_layer_commit; c->base.base.destroy = client_vk_compositor_destroy; diff --git a/src/xrt/compositor/main/comp_compositor.c b/src/xrt/compositor/main/comp_compositor.c index 9de75f291..006c8b88b 100644 --- a/src/xrt/compositor/main/comp_compositor.c +++ b/src/xrt/compositor/main/comp_compositor.c @@ -440,6 +440,15 @@ compositor_layer_cylinder(struct xrt_compositor *xc, return do_single(xc, xdev, xsc, data); } +static xrt_result_t +compositor_layer_equirect1(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data) +{ + return do_single(xc, xdev, xsc, data); +} + static xrt_result_t compositor_layer_equirect2(struct xrt_compositor *xc, struct xrt_device *xdev, @@ -513,6 +522,13 @@ compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id) image = &layer->scs[0]->images[cyl->sub.image_index]; comp_renderer_set_cylinder_layer(c->r, i, image, data); } break; + case XRT_LAYER_EQUIRECT1: { + struct xrt_layer_equirect1_data *eq = + &layer->data.equirect1; + struct comp_swapchain_image *image; + image = &layer->scs[0]->images[eq->sub.image_index]; + comp_renderer_set_equirect1_layer(c->r, i, image, data); + } break; case XRT_LAYER_EQUIRECT2: { struct xrt_layer_equirect2_data *eq = &layer->data.equirect2; @@ -1308,6 +1324,7 @@ xrt_gfx_provider_create_native(struct xrt_device *xdev) c->base.base.layer_quad = compositor_layer_quad; c->base.base.layer_cube = compositor_layer_cube; c->base.base.layer_cylinder = compositor_layer_cylinder; + c->base.base.layer_equirect1 = compositor_layer_equirect1; c->base.base.layer_equirect2 = compositor_layer_equirect2; c->base.base.layer_commit = compositor_layer_commit; c->base.base.poll_events = compositor_poll_events; diff --git a/src/xrt/compositor/main/comp_layer.c b/src/xrt/compositor/main/comp_layer.c index 822290c01..530d7081d 100644 --- a/src/xrt/compositor/main/comp_layer.c +++ b/src/xrt/compositor/main/comp_layer.c @@ -304,6 +304,7 @@ comp_layer_draw(struct comp_render_layer *self, case XRT_LAYER_EQUIRECT2: _update_mvp_matrix(self, eye, vp); break; case XRT_LAYER_STEREO_PROJECTION_DEPTH: case XRT_LAYER_CUBE: + case XRT_LAYER_EQUIRECT1: // Should never end up here. assert(false); } diff --git a/src/xrt/compositor/main/comp_renderer.c b/src/xrt/compositor/main/comp_renderer.c index 65df4ec53..d425548a9 100644 --- a/src/xrt/compositor/main/comp_renderer.c +++ b/src/xrt/compositor/main/comp_renderer.c @@ -574,6 +574,42 @@ comp_renderer_set_projection_layer(struct comp_renderer *r, l->transformation[1].extent = data->stereo.r.sub.rect.extent; } +void +comp_renderer_set_equirect1_layer(struct comp_renderer *r, + uint32_t layer, + struct comp_swapchain_image *image, + struct xrt_layer_data *data) +{ + + struct xrt_vec3 s = {1.0f, 1.0f, 1.0f}; + struct xrt_matrix_4x4 model_matrix; + math_matrix_4x4_model(&data->equirect1.pose, &s, &model_matrix); + + comp_layer_set_flip_y(r->lr->layers[layer], data->flip_y); + + struct comp_render_layer *l = r->lr->layers[layer]; + l->type = XRT_LAYER_EQUIRECT1; + l->visibility = data->equirect1.visibility; + l->flags = data->flags; + l->view_space = + (data->flags & XRT_LAYER_COMPOSITION_VIEW_SPACE_BIT) != 0; + l->transformation_ubo_binding = r->lr->transformation_ubo_binding; + l->texture_binding = r->lr->texture_binding; + + comp_layer_update_descriptors( + l, image->repeat_sampler, + get_image_view(image, data->flags, + data->equirect1.sub.array_index)); + + // TODO! + // comp_layer_update_equirect1_descriptor(l, &data->equirect1); + + for (uint32_t i = 0; i < 2; i++) { + l->transformation[i].offset = data->equirect1.sub.rect.offset; + l->transformation[i].extent = data->equirect1.sub.rect.extent; + } +} + void comp_renderer_set_equirect2_layer(struct comp_renderer *r, uint32_t layer, diff --git a/src/xrt/compositor/main/comp_renderer.h b/src/xrt/compositor/main/comp_renderer.h index f97aa3821..9eb12acb5 100644 --- a/src/xrt/compositor/main/comp_renderer.h +++ b/src/xrt/compositor/main/comp_renderer.h @@ -73,6 +73,12 @@ comp_renderer_set_cylinder_layer(struct comp_renderer *r, struct comp_swapchain_image *image, struct xrt_layer_data *data); +void +comp_renderer_set_equirect1_layer(struct comp_renderer *r, + uint32_t layer, + struct comp_swapchain_image *image, + struct xrt_layer_data *data); + void comp_renderer_set_equirect2_layer(struct comp_renderer *r, uint32_t layer, diff --git a/src/xrt/include/xrt/xrt_compositor.h b/src/xrt/include/xrt/xrt_compositor.h index 25ba00a82..4a8733ef1 100644 --- a/src/xrt/include/xrt/xrt_compositor.h +++ b/src/xrt/include/xrt/xrt_compositor.h @@ -96,6 +96,7 @@ enum xrt_layer_type XRT_LAYER_QUAD, XRT_LAYER_CUBE, XRT_LAYER_CYLINDER, + XRT_LAYER_EQUIRECT1, XRT_LAYER_EQUIRECT2, }; @@ -249,6 +250,24 @@ struct xrt_layer_cylinder_data float aspect_ratio; }; +/*! + * All the pure data values associated with a equirect1 layer. + * + * The @ref xrt_swapchain references and @ref xrt_device are provided outside of + * this struct. + */ +struct xrt_layer_equirect1_data +{ + enum xrt_layer_eye_visibility visibility; + + struct xrt_sub_image sub; + + struct xrt_pose pose; + float radius; + struct xrt_vec2 scale; + struct xrt_vec2 bias; +}; + /*! * All the pure data values associated with a equirect2 layer. * @@ -327,6 +346,7 @@ struct xrt_layer_data struct xrt_layer_quad_data quad; struct xrt_layer_cube_data cube; struct xrt_layer_cylinder_data cylinder; + struct xrt_layer_equirect1_data equirect1; struct xrt_layer_equirect2_data equirect2; }; }; @@ -722,6 +742,20 @@ struct xrt_compositor struct xrt_swapchain *xsc, const struct xrt_layer_data *data); + /*! + * Adds a equirect1 layer for submission. + * + * @param xc Self pointer + * @param xdev The device the layer is relative to. + * @param xsc Swapchain. + * @param data All of the pure data bits. + */ + xrt_result_t (*layer_equirect1)(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data); + + /*! * Adds a equirect2 layer for submission. * @@ -981,6 +1015,23 @@ xrt_comp_layer_cylinder(struct xrt_compositor *xc, return xc->layer_cylinder(xc, xdev, xsc, data); } + +/*! + * @copydoc xrt_compositor::layer_equirect1 + * + * Helper for calling through the function pointer. + * + * @public @memberof xrt_compositor + */ +static inline xrt_result_t +xrt_comp_layer_equirect1(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data) +{ + return xc->layer_equirect1(xc, xdev, xsc, data); +} + /*! * @copydoc xrt_compositor::layer_equirect2 * diff --git a/src/xrt/ipc/client/ipc_client_compositor.c b/src/xrt/ipc/client/ipc_client_compositor.c index 3c310a97f..32ebb1404 100644 --- a/src/xrt/ipc/client/ipc_client_compositor.c +++ b/src/xrt/ipc/client/ipc_client_compositor.c @@ -591,6 +591,15 @@ ipc_compositor_layer_cylinder(struct xrt_compositor *xc, return handle_layer(xc, xdev, xsc, data, XRT_LAYER_CYLINDER); } +static xrt_result_t +ipc_compositor_layer_equirect1(struct xrt_compositor *xc, + struct xrt_device *xdev, + struct xrt_swapchain *xsc, + const struct xrt_layer_data *data) +{ + return handle_layer(xc, xdev, xsc, data, XRT_LAYER_EQUIRECT1); +} + static xrt_result_t ipc_compositor_layer_equirect2(struct xrt_compositor *xc, struct xrt_device *xdev, @@ -785,6 +794,7 @@ ipc_client_compositor_create(struct ipc_connection *ipc_c, c->base.base.layer_quad = ipc_compositor_layer_quad; c->base.base.layer_cube = ipc_compositor_layer_cube; c->base.base.layer_cylinder = ipc_compositor_layer_cylinder; + c->base.base.layer_equirect1 = ipc_compositor_layer_equirect1; c->base.base.layer_equirect2 = ipc_compositor_layer_equirect2; c->base.base.layer_commit = ipc_compositor_layer_commit; c->base.base.destroy = ipc_compositor_destroy; diff --git a/src/xrt/ipc/server/ipc_server_per_client_thread.c b/src/xrt/ipc/server/ipc_server_per_client_thread.c index 27a8a4421..79fb9a95b 100644 --- a/src/xrt/ipc/server/ipc_server_per_client_thread.c +++ b/src/xrt/ipc/server/ipc_server_per_client_thread.c @@ -164,6 +164,7 @@ client_loop(volatile struct ipc_client_state *ics) rl->data.quad.sub.image_index = 0; rl->data.cube.sub.image_index = 0; rl->data.cylinder.sub.image_index = 0; + rl->data.equirect1.sub.image_index = 0; rl->data.equirect2.sub.image_index = 0; //! @todo set rects or array index? diff --git a/src/xrt/ipc/server/ipc_server_process.c b/src/xrt/ipc/server/ipc_server_process.c index 0ae1873b8..19855dc16 100644 --- a/src/xrt/ipc/server/ipc_server_process.c +++ b/src/xrt/ipc/server/ipc_server_process.c @@ -868,6 +868,25 @@ _update_cylinder_layer(struct xrt_compositor *xc, return true; } +static bool +_update_equirect1_layer(struct xrt_compositor *xc, + volatile struct ipc_client_state *ics, + volatile struct ipc_layer_entry *layer, + uint32_t i) +{ + struct xrt_device *xdev; + struct xrt_swapchain *xcs; + struct xrt_layer_data *data; + + if (!do_single(xc, ics, layer, i, "equirect1", &xdev, &xcs, &data)) { + return false; + } + + xrt_comp_layer_equirect1(xc, xdev, xcs, data); + + return true; +} + static bool _update_equirect2_layer(struct xrt_compositor *xc, volatile struct ipc_client_state *ics, @@ -974,6 +993,12 @@ _update_layers(struct ipc_server *s, struct xrt_compositor *xc) return false; } break; + case XRT_LAYER_EQUIRECT1: + if (!_update_equirect1_layer(xc, ics, layer, + i)) { + return false; + } + break; case XRT_LAYER_EQUIRECT2: if (!_update_equirect2_layer(xc, ics, layer, i)) { diff --git a/src/xrt/state_trackers/oxr/oxr_instance.c b/src/xrt/state_trackers/oxr/oxr_instance.c index 7c01c3b69..b13a7679b 100644 --- a/src/xrt/state_trackers/oxr/oxr_instance.c +++ b/src/xrt/state_trackers/oxr/oxr_instance.c @@ -353,6 +353,9 @@ oxr_instance_create(struct oxr_logger *log, CHECK_LAYER_TYPE("projection layers with depth images", layer_stereo_projection_depth); #endif +#ifdef XRT_FEATURE_OPENXR_LAYER_EQUIRECT1 + CHECK_LAYER_TYPE("equirect1 layers", layer_equirect1); +#endif #ifdef XRT_FEATURE_OPENXR_LAYER_EQUIRECT2 CHECK_LAYER_TYPE("equirect2 layers", layer_equirect2); #endif diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index c23450dd1..1469ffa40 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -1315,9 +1315,7 @@ verify_equirect1_layer(struct xrt_compositor *xc, layer_index, equirect->radius); } - //! @todo Not all fields validated. - return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, - "XrCompositionLayerEquirectKHR not implemented"); + return XR_SUCCESS; #endif } @@ -1798,7 +1796,7 @@ submit_cylinder_layer(struct oxr_session *sess, return XR_SUCCESS; } -static void +static XrResult submit_equirect1_layer(struct oxr_session *sess, struct xrt_compositor *xc, struct oxr_logger *log, @@ -1807,7 +1805,54 @@ submit_equirect1_layer(struct oxr_session *sess, struct xrt_pose *inv_offset, uint64_t timestamp) { - // Not implemented + struct oxr_swapchain *sc = XRT_CAST_OXR_HANDLE_TO_PTR( + struct oxr_swapchain *, equirect->subImage.swapchain); + struct oxr_space *spc = + XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_space *, equirect->space); + + enum xrt_layer_composition_flags flags = + convert_layer_flags(equirect->layerFlags); + + struct xrt_pose *pose_ptr = (struct xrt_pose *)&equirect->pose; + + struct xrt_pose pose; + if (!handle_space(log, sess, spc, pose_ptr, inv_offset, timestamp, + &pose)) { + return XR_SUCCESS; + } + + if (spc->is_reference && spc->type == XR_REFERENCE_SPACE_TYPE_VIEW) { + flags |= XRT_LAYER_COMPOSITION_VIEW_SPACE_BIT; + } + + struct xrt_layer_data data; + U_ZERO(&data); + data.type = XRT_LAYER_EQUIRECT1; + data.name = XRT_INPUT_GENERIC_HEAD_POSE; + data.timestamp = timestamp; + data.flags = flags; + + struct xrt_rect *rect = + (struct xrt_rect *)&equirect->subImage.imageRect; + + data.equirect1.visibility = + convert_eye_visibility(equirect->eyeVisibility); + data.equirect1.sub.image_index = sc->released.index; + data.equirect1.sub.array_index = equirect->subImage.imageArrayIndex; + data.equirect1.sub.rect = *rect; + data.equirect1.pose = pose; + + data.equirect1.radius = equirect->radius; + + struct xrt_vec2 *scale = (struct xrt_vec2 *)&equirect->scale; + struct xrt_vec2 *bias = (struct xrt_vec2 *)&equirect->bias; + + data.equirect1.scale = *scale; + data.equirect1.bias = *bias; + + CALL_CHK(xrt_comp_layer_equirect1(xc, head, sc->swapchain, &data)); + + return XR_SUCCESS; } static void