diff --git a/doc/changes/compositor/mr.479.md b/doc/changes/compositor/mr.479.md new file mode 100644 index 000000000..911b33e20 --- /dev/null +++ b/doc/changes/compositor/mr.479.md @@ -0,0 +1 @@ +compositor and clients: Use a generic typedef to represent the platform-specific graphics buffer, allowing use of `AHardwareBuffer` on recent Android. diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 1fd1ca2c6..357f8dc1b 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -200,4 +200,7 @@ if(XRT_HAVE_VULKAN) add_library(aux_vk STATIC ${VK_SOURCE_FILES}) target_link_libraries(aux_vk PUBLIC aux-includes) target_link_libraries(aux_vk PUBLIC Vulkan::Vulkan) + if(ANDROID) + target_link_libraries(aux_vk PUBLIC ${ANDROID_LIBRARY}) + endif() endif() diff --git a/src/xrt/auxiliary/vk/vk_helpers.c b/src/xrt/auxiliary/vk/vk_helpers.c index b13a72dca..9de663174 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.c +++ b/src/xrt/auxiliary/vk/vk_helpers.c @@ -303,14 +303,22 @@ vk_create_image_from_native(struct vk_bundle *vk, // Nothing to cleanup return ret; } -#ifdef XRT_OS_ANDROID - ret = VK_ERROR_INITIALIZATION_FAILED; -#else +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) VkImportMemoryFdInfoKHR import_memory_info = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, .fd = image_native->handle, }; +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + VkImportAndroidHardwareBufferInfoANDROID import_memory_info = { + .sType = + VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, + .pNext = NULL, + .buffer = image_native->handle, + }; +#else +#error "need port" +#endif VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, .pNext = &import_memory_info, @@ -320,7 +328,6 @@ vk_create_image_from_native(struct vk_bundle *vk, ret = vk_alloc_and_bind_image_memory(vk, image, image_native->size, &dedicated_memory_info, out_mem, NULL); -#endif // We have consumed this fd now, make sure it's not freed again. image_native->handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; @@ -681,6 +688,9 @@ vk_get_device_functions(struct vk_bundle *vk) vk->vkMapMemory = GET_DEV_PROC(vk, vkMapMemory); vk->vkUnmapMemory = GET_DEV_PROC(vk, vkUnmapMemory); vk->vkGetMemoryFdKHR = GET_DEV_PROC(vk, vkGetMemoryFdKHR); +#ifdef VK_USE_PLATFORM_ANDROID_KHR + vk->vkGetMemoryAndroidHardwareBufferANDROID = GET_DEV_PROC(vk, vkGetMemoryAndroidHardwareBufferANDROID); +#endif vk->vkCreateBuffer = GET_DEV_PROC(vk, vkCreateBuffer); vk->vkDestroyBuffer = GET_DEV_PROC(vk, vkDestroyBuffer); vk->vkBindBufferMemory = GET_DEV_PROC(vk, vkBindBufferMemory); diff --git a/src/xrt/auxiliary/vk/vk_helpers.h b/src/xrt/auxiliary/vk/vk_helpers.h index 84b440816..65f90cefe 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.h +++ b/src/xrt/auxiliary/vk/vk_helpers.h @@ -109,6 +109,10 @@ struct vk_bundle PFN_vkUnmapMemory vkUnmapMemory; PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR; +#ifdef VK_USE_PLATFORM_ANDROID_KHR + PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID; +#endif + PFN_vkCreateBuffer vkCreateBuffer; PFN_vkDestroyBuffer vkDestroyBuffer; PFN_vkBindBufferMemory vkBindBufferMemory; diff --git a/src/xrt/auxiliary/vk/vk_image_allocator.c b/src/xrt/auxiliary/vk/vk_image_allocator.c index 8386457cd..2ab7d7f83 100644 --- a/src/xrt/auxiliary/vk/vk_image_allocator.c +++ b/src/xrt/auxiliary/vk/vk_image_allocator.c @@ -12,6 +12,10 @@ #include "vk/vk_image_allocator.h" +#if defined(XRT_OS_ANDROID) +#include +#endif + #ifdef XRT_OS_LINUX #include #endif @@ -23,11 +27,12 @@ * */ -#ifdef XRT_OS_LINUX +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) + static VkResult -get_device_memory_fd(struct vk_bundle *vk, - VkDeviceMemory device_memory, - int *out_fd) +get_device_memory_handle(struct vk_bundle *vk, + VkDeviceMemory device_memory, + xrt_graphics_buffer_handle_t *out_handle) { // vkGetMemoryFdKHR parameter VkMemoryGetFdInfoKHR fd_info = { @@ -35,6 +40,7 @@ get_device_memory_fd(struct vk_bundle *vk, .memory = device_memory, .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, }; + int fd; VkResult ret = vk->vkGetMemoryFdKHR(vk->device, &fd_info, &fd); if (ret != VK_SUCCESS) { @@ -42,9 +48,39 @@ get_device_memory_fd(struct vk_bundle *vk, // vk_result_string(ret)); return ret; } - *out_fd = fd; + + *out_handle = fd; + return ret; } + +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + +static VkResult +get_device_memory_handle(struct vk_bundle *vk, + VkDeviceMemory device_memory, + xrt_graphics_buffer_handle_t *out_handle) +{ + // vkGetMemoryFdKHR parameter + VkMemoryGetAndroidHardwareBufferInfoANDROID ahb_info = { + .sType = + VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, + .pNext = NULL, + .memory = device_memory, + }; + + AHardwareBuffer *buf = NULL; + VkResult ret = vk->vkGetMemoryAndroidHardwareBufferANDROID( + vk->device, &ahb_info, &buf); + if (ret != VK_SUCCESS) { + return ret; + } + + *out_handle = buf; + + return ret; +} + #endif static VkResult @@ -94,7 +130,6 @@ create_image(struct vk_bundle *vk, /* * Create and bind the memory. */ -#ifdef XRT_OS_LINUX // vkAllocateMemory parameters VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, @@ -102,17 +137,29 @@ create_image(struct vk_bundle *vk, .buffer = VK_NULL_HANDLE, }; +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) + VkExportMemoryAllocateInfo export_alloc_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, .pNext = &dedicated_memory_info, .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, }; +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + + VkExportMemoryAllocateInfo export_alloc_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, + .pNext = &dedicated_memory_info, + .handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, + }; + +#else +#error "need port" +#endif + ret = vk_alloc_and_bind_image_memory( vk, image, SIZE_MAX, &export_alloc_info, &device_memory, &size); -#else - ret = VK_ERROR_INITIALIZATION_FAILED; -#endif if (ret != VK_SUCCESS) { U_LOG_E("vkAllocateMemory: %s", vk_result_string(ret)); vk->vkDestroyImage(vk->device, image, NULL); @@ -187,6 +234,48 @@ vk_ic_allocate(struct vk_bundle *vk, return ret; } +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + +static void +release_handle(xrt_graphics_buffer_handle_t handle) +{ + if (handle != NULL) { + AHardwareBuffer_release(handle); + } +} + +static xrt_graphics_buffer_handle_t +ref_handle(xrt_graphics_buffer_handle_t handle) +{ + if (handle != NULL) { + AHardwareBuffer_acquire(handle); + } + + return handle; +} + +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) + +static void +release_handle(xrt_graphics_buffer_handle_t handle) +{ + if (handle >= 0) { + close(handle); + } +} + +static xrt_graphics_buffer_handle_t +ref_handle(xrt_graphics_buffer_handle_t handle) +{ + if (handle >= 0) { + return dup(handle); + } + + return -1; +} + +#endif + /*! * Imports and set images from the given FDs. */ @@ -205,37 +294,33 @@ vk_ic_from_natives(struct vk_bundle *vk, size_t i = 0; -#ifdef XRT_OS_LINUX for (; i < num_images; i++) { - // Ensure that all fds are consumed or none are. - int fd = dup(native_images[i].handle); + // Ensure that all handles are consumed or none are. + xrt_graphics_buffer_handle_t buf = + ref_handle(native_images[i].handle); ret = vk_create_image_from_native(vk, xscci, &native_images[i], &out_vkic->images[i].handle, &out_vkic->images[i].memory); if (ret != VK_SUCCESS) { - close(fd); + release_handle(buf); break; } - native_images[i].handle = fd; + native_images[i].handle = buf; } -#endif - // Set the fields. out_vkic->num_images = num_images; out_vkic->info = *xscci; if (ret == VK_SUCCESS) { -#ifdef XRT_OS_LINUX - // We have consumed all fds now, close all of the copies we + // We have consumed all handles now, close all of the copies we // made, all this to make sure we do all or nothing. for (size_t k = 0; k < num_images; k++) { - close(native_images[k].handle); + release_handle(native_images[k].handle); native_images[k].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; native_images[k].size = 0; } -#endif return ret; } @@ -261,19 +346,18 @@ vk_ic_destroy(struct vk_bundle *vk, struct vk_image_collection *vkic) U_ZERO(&vkic->info); } -#ifdef XRT_OS_LINUX VkResult -vk_ic_get_fds(struct vk_bundle *vk, - struct vk_image_collection *vkic, - uint32_t max_fds, - int *out_fds) +vk_ic_get_handles(struct vk_bundle *vk, + struct vk_image_collection *vkic, + uint32_t max_handles, + xrt_graphics_buffer_handle_t *out_handles) { VkResult ret = VK_SUCCESS; size_t i = 0; - for (; i < vkic->num_images && i < max_fds; i++) { - ret = get_device_memory_fd(vk, vkic->images[i].memory, - &out_fds[i]); + for (; i < vkic->num_images && i < max_handles; i++) { + ret = get_device_memory_handle(vk, vkic->images[i].memory, + &out_handles[i]); if (ret != VK_SUCCESS) { break; } @@ -287,10 +371,9 @@ vk_ic_get_fds(struct vk_bundle *vk, // succeeded and needs to be closed. If i is zero no call succeeded. while (i > 0) { i--; - close(out_fds[i]); - out_fds[i] = -1; + release_handle(out_handles[i]); + out_handles[i] = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; } return ret; } -#endif diff --git a/src/xrt/auxiliary/vk/vk_image_allocator.h b/src/xrt/auxiliary/vk/vk_image_allocator.h index 2f8cf98ad..d6c9d1308 100644 --- a/src/xrt/auxiliary/vk/vk_image_allocator.h +++ b/src/xrt/auxiliary/vk/vk_image_allocator.h @@ -66,21 +66,20 @@ vk_ic_from_natives(struct vk_bundle *vk, void vk_ic_destroy(struct vk_bundle *vk, struct vk_image_collection *vkic); -#ifdef XRT_OS_LINUX /*! - * Get the FDs for the images, this is a all or nothing function. - * The ownership is transferred from the images to the caller so it is - * responsible for them to be closed just like with vkGetMemoryFdKHR. + * Get the native handles (FDs on desktop Linux) for the images, this is a all + * or nothing function. The ownership is transferred from the images to the + * caller so it is responsible for them to be closed just like with + * vkGetMemoryFdKHR. * * @see * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_external_memory_fd.html */ VkResult -vk_ic_get_fds(struct vk_bundle *vk, - struct vk_image_collection *vkic, - uint32_t max_fds, - int *out_fds); -#endif +vk_ic_get_handles(struct vk_bundle *vk, + struct vk_image_collection *vkic, + uint32_t max_handles, + xrt_graphics_buffer_handle_t *out_handles); /*! diff --git a/src/xrt/compositor/client/comp_gl_client.c b/src/xrt/compositor/client/comp_gl_client.c index 8d3d4e33b..3a94d79c7 100644 --- a/src/xrt/compositor/client/comp_gl_client.c +++ b/src/xrt/compositor/client/comp_gl_client.c @@ -354,7 +354,6 @@ client_gl_compositor_init(struct client_gl_compositor *c, gladLoadGL(get_gl_procaddr); #elif defined(XRT_HAVE_OPENGLES) gladLoadGLES2(get_gl_procaddr); - gladLoadEGL(display, get_gl_procaddr); #endif // @todo log this to a proper logger. #define CHECK_REQUIRED_EXTENSION(EXT) \ diff --git a/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c b/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c index 8ce24fa31..d71b205fa 100644 --- a/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c +++ b/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c @@ -223,9 +223,14 @@ client_gl_eglimage_swapchain_create( free(sc); return NULL; } +#if defined(XRT_OS_ANDROID) + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, + sc->egl_images[i]); +#else glEGLImageTargetTexture2DOES( info->array_size == 1 ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY, sc->egl_images[i]); +#endif } return &sc->base.base.base; diff --git a/src/xrt/compositor/main/comp_swapchain.c b/src/xrt/compositor/main/comp_swapchain.c index 4e7566d64..4d7eb468a 100644 --- a/src/xrt/compositor/main/comp_swapchain.c +++ b/src/xrt/compositor/main/comp_swapchain.c @@ -15,6 +15,10 @@ #include #include +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) +#include +#endif + /* * @@ -256,17 +260,13 @@ comp_swapchain_create(struct xrt_compositor *xc, return XRT_ERROR_VULKAN; } -#ifdef XRT_OS_LINUX - int fds[ARRAY_SIZE(sc->vkic.images)]; + xrt_graphics_buffer_handle_t handles[ARRAY_SIZE(sc->vkic.images)]; - vk_ic_get_fds(&c->vk, &sc->vkic, ARRAY_SIZE(fds), fds); + vk_ic_get_handles(&c->vk, &sc->vkic, ARRAY_SIZE(handles), handles); for (uint32_t i = 0; i < sc->vkic.num_images; i++) { - sc->base.images[i].handle = fds[i]; + sc->base.images[i].handle = handles[i]; sc->base.images[i].size = sc->vkic.images[i].size; } -#else -#error "OS not supported" -#endif do_post_create_vulkan_setup(c, sc); @@ -319,7 +319,14 @@ comp_swapchain_really_destroy(struct comp_swapchain *sc) if (!xrt_graphics_buffer_is_valid(sc->base.images[i].handle)) { continue; } +//! @todo move to helper functions - move them out of IPC +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) + AHardwareBuffer_release(sc->base.images[i].handle); +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) close(sc->base.images[i].handle); +#else +#error "need port" +#endif sc->base.images[i].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; }