xrt: Use our generic graphics buffer typedefs all over.

This adds some Android support in composition clients,
and fixes the breakage from 2 commits ago.

Thanks to Jakob for finding my error in an earlier version.
This commit is contained in:
Ryan Pavlik 2020-07-20 16:07:32 -05:00
parent fc73ba0401
commit 9087d1c7a9
9 changed files with 163 additions and 52 deletions

View file

@ -0,0 +1 @@
compositor and clients: Use a generic typedef to represent the platform-specific graphics buffer, allowing use of `AHardwareBuffer` on recent Android.

View file

@ -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()

View file

@ -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);

View file

@ -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;

View file

@ -12,6 +12,10 @@
#include "vk/vk_image_allocator.h"
#if defined(XRT_OS_ANDROID)
#include <android/hardware_buffer.h>
#endif
#ifdef XRT_OS_LINUX
#include <unistd.h>
#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

View file

@ -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);
/*!

View file

@ -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) \

View file

@ -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;

View file

@ -15,6 +15,10 @@
#include <stdlib.h>
#include <unistd.h>
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
#include <android/hardware_buffer.h>
#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;
}