diff --git a/CMakeLists.txt b/CMakeLists.txt index 07d0d0142..7aeb75b05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -430,6 +430,9 @@ endif() if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_EQUIRECT1) set(XRT_FEATURE_OPENXR_LAYER_EQUIRECT1 OFF) endif() +if(NOT DEFINED XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT) + set(XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT ON) +endif() # Defaults for OpenXR spaces if(NOT DEFINED XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR) @@ -642,6 +645,7 @@ message(STATUS "# FEATURE_OPENXR_LAYER_CYLINDER: ${XRT_FEATURE message(STATUS "# FEATURE_OPENXR_LAYER_DEPTH: ${XRT_FEATURE_OPENXR_LAYER_DEPTH}") message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT1: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT1}") message(STATUS "# FEATURE_OPENXR_LAYER_EQUIRECT2: ${XRT_FEATURE_OPENXR_LAYER_EQUIRECT2}") +message(STATUS "# FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT ${XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT}") message(STATUS "# FEATURE_OPENXR_OVERLAY: ${XRT_FEATURE_OPENXR_OVERLAY}") message(STATUS "# FEATURE_OPENXR_SPACE_LOCAL_FLOOR: ${XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR}") message(STATUS "# FEATURE_OPENXR_SPACE_UNBOUNDED: ${XRT_FEATURE_OPENXR_SPACE_UNBOUNDED}") diff --git a/scripts/generate_oxr_ext_support.py b/scripts/generate_oxr_ext_support.py index 6bce59eb1..af604a948 100755 --- a/scripts/generate_oxr_ext_support.py +++ b/scripts/generate_oxr_ext_support.py @@ -64,6 +64,7 @@ EXTENSIONS = ( ['XR_EXT_local_floor', 'XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR'], ['XR_EXT_palm_pose', 'XRT_FEATURE_OPENXR_INTERACTION_EXT_PALM_POSE'], ['XR_EXT_samsung_odyssey_controller', 'XRT_FEATURE_OPENXR_INTERACTION_WINMR'], + ['XR_FB_composition_layer_image_layout', 'XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT'], ['XR_FB_display_refresh_rate', 'XRT_FEATURE_OPENXR_DISPLAY_REFRESH_RATE'], ['XR_ML_ml2_controller_interaction', 'XRT_FEATURE_OPENXR_INTERACTION_ML2'], ['XR_MND_headless', 'XRT_FEATURE_OPENXR_HEADLESS'], diff --git a/src/xrt/include/xrt/xrt_config_build.h.cmake_in b/src/xrt/include/xrt/xrt_config_build.h.cmake_in index ff3c8362b..537e738b2 100644 --- a/src/xrt/include/xrt/xrt_config_build.h.cmake_in +++ b/src/xrt/include/xrt/xrt_config_build.h.cmake_in @@ -46,6 +46,7 @@ #cmakedefine XRT_FEATURE_OPENXR_LAYER_DEPTH #cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT1 #cmakedefine XRT_FEATURE_OPENXR_LAYER_EQUIRECT2 +#cmakedefine XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT #cmakedefine XRT_FEATURE_OPENXR_OVERLAY #cmakedefine XRT_FEATURE_OPENXR_SPACE_LOCAL_FLOOR #cmakedefine XRT_FEATURE_OPENXR_SPACE_UNBOUNDED diff --git a/src/xrt/state_trackers/oxr/oxr_extension_support.h b/src/xrt/state_trackers/oxr/oxr_extension_support.h index 704cda116..92fe1fbed 100644 --- a/src/xrt/state_trackers/oxr/oxr_extension_support.h +++ b/src/xrt/state_trackers/oxr/oxr_extension_support.h @@ -372,6 +372,18 @@ #endif +/* + * XR_FB_composition_layer_image_layout + */ +#if defined(XR_FB_composition_layer_image_layout) && defined(XRT_FEATURE_OPENXR_LAYER_FB_LAYER_IMAGE_LAYOUT) +#define OXR_HAVE_FB_composition_layer_image_layout +#define OXR_EXTENSION_SUPPORT_FB_composition_layer_image_layout(_) \ + _(FB_composition_layer_image_layout, FB_COMPOSITION_LAYER_IMAGE_LAYOUT) +#else +#define OXR_EXTENSION_SUPPORT_FB_composition_layer_image_layout(_) +#endif + + /* * XR_FB_display_refresh_rate */ @@ -585,6 +597,7 @@ OXR_EXTENSION_SUPPORT_EXT_local_floor(_) \ OXR_EXTENSION_SUPPORT_EXT_palm_pose(_) \ OXR_EXTENSION_SUPPORT_EXT_samsung_odyssey_controller(_) \ + OXR_EXTENSION_SUPPORT_FB_composition_layer_image_layout(_) \ OXR_EXTENSION_SUPPORT_FB_display_refresh_rate(_) \ OXR_EXTENSION_SUPPORT_ML_ml2_controller_interaction(_) \ OXR_EXTENSION_SUPPORT_MND_headless(_) \ diff --git a/src/xrt/state_trackers/oxr/oxr_session_frame_end.c b/src/xrt/state_trackers/oxr/oxr_session_frame_end.c index 717060577..3bae884c6 100644 --- a/src/xrt/state_trackers/oxr/oxr_session_frame_end.c +++ b/src/xrt/state_trackers/oxr/oxr_session_frame_end.c @@ -161,6 +161,30 @@ fill_in_color_scale_bias(struct oxr_session *sess, #endif // OXR_HAVE_KHR_composition_layer_color_scale_bias } +static void +fill_in_y_flip(struct oxr_session *sess, const XrCompositionLayerBaseHeader *layer, struct xrt_layer_data *xlayer_data) +{ +#ifdef OXR_HAVE_FB_composition_layer_image_layout + // Is the extension enabled? + if (!sess->sys->inst->extensions.FB_composition_layer_image_layout) { + return; + } + + const XrCompositionLayerImageLayoutFB *layer_image_layout = OXR_GET_INPUT_FROM_CHAIN( + layer->next, XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB, XrCompositionLayerImageLayoutFB); + + // Is the layer here, and does it have the flag, if not nothing to do. + if (layer_image_layout == NULL || + (layer_image_layout->flags & XR_COMPOSITION_LAYER_IMAGE_LAYOUT_VERTICAL_FLIP_BIT_FB) == 0) { + return; + } + + // All conditions met. + xlayer_data->flip_y = true; + +#endif // OXR_HAVE_FB_composition_layer_image_layout +} + static void fill_in_sub_image(const struct oxr_swapchain *sc, const XrSwapchainSubImage *oxr_sub, struct xrt_sub_image *xsub) { @@ -962,6 +986,7 @@ submit_quad_layer(struct oxr_session *sess, data.quad.size = *size; fill_in_sub_image(sc, &quad->subImage, &data.quad.sub); fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)quad, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)quad, &data); xrt_result_t xret = xrt_comp_layer_quad(xc, head, sc->swapchain, &data); OXR_CHECK_XRET(log, sess, xret, xrt_comp_layer_quad); @@ -1017,6 +1042,7 @@ submit_projection_layer(struct oxr_session *sess, fill_in_sub_image(scs[0], &proj->views[0].subImage, &data.stereo.l.sub); fill_in_sub_image(scs[1], &proj->views[1].subImage, &data.stereo.r.sub); fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)proj, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)proj, &data); #ifdef OXR_HAVE_KHR_composition_layer_depth const XrCompositionLayerDepthInfoKHR *d_l = OXR_GET_INPUT_FROM_CHAIN( @@ -1110,6 +1136,7 @@ submit_cube_layer(struct oxr_session *sess, data.cube.sub.image_index = sc->released.index; data.cube.sub.array_index = cube->imageArrayIndex; fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)cube, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)cube, &data); struct xrt_pose pose = { .orientation = @@ -1173,6 +1200,7 @@ submit_cylinder_layer(struct oxr_session *sess, data.cylinder.aspect_ratio = cylinder->aspectRatio; fill_in_sub_image(sc, &cylinder->subImage, &data.cylinder.sub); fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)cylinder, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)cylinder, &data); xrt_result_t xret = xrt_comp_layer_cylinder(xc, head, sc->swapchain, &data); OXR_CHECK_XRET(log, sess, xret, xrt_comp_layer_cylinder); @@ -1217,6 +1245,7 @@ submit_equirect1_layer(struct oxr_session *sess, data.equirect1.radius = equirect->radius; fill_in_sub_image(sc, &equirect->subImage, &data.equirect1.sub); fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)equirect, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)equirect, &data); struct xrt_vec2 *scale = (struct xrt_vec2 *)&equirect->scale; @@ -1280,6 +1309,7 @@ submit_equirect2_layer(struct oxr_session *sess, data.equirect2.lower_vertical_angle = equirect->lowerVerticalAngle; fill_in_sub_image(sc, &equirect->subImage, &data.equirect2.sub); fill_in_color_scale_bias(sess, (XrCompositionLayerBaseHeader *)equirect, &data); + fill_in_y_flip(sess, (XrCompositionLayerBaseHeader *)equirect, &data); xrt_result_t xret = xrt_comp_layer_equirect2(xc, head, sc->swapchain, &data); OXR_CHECK_XRET(log, sess, xret, xrt_comp_layer_equirect2);