Mesa (main): v3dv: add Android support
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Dec 21 09:53:29 UTC 2021
Module: Mesa
Branch: main
Commit: 2686c5419d67aab365c83647094a537a31a89085
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=2686c5419d67aab365c83647094a537a31a89085
Author: Roman Stratiienko <r.stratiienko at gmail.com>
Date: Wed Dec 8 12:15:38 2021 +0200
v3dv: add Android support
Acknowledgements to android-rpi team and lineage-rpi maintainer (KonstaT)
for creating/testing initial vulkan support. Their experience was used as
a baseline for this work.
Most of the code is a copy of turnip and anv.
Improved by cleaning dEQP failures:
- Improved gralloc support (use allocation time stride, size, modifier).
- Fixed some dEQP crashes due to memory allocation issues.
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Signed-off-by: Roman Stratiienko <r.stratiienko at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14016>
---
src/broadcom/vulkan/meson.build | 6 +
src/broadcom/vulkan/v3dv_android.c | 539 +++++++++++++++++++++++++++++++++++++
src/broadcom/vulkan/v3dv_device.c | 3 +
src/broadcom/vulkan/v3dv_image.c | 41 +++
src/broadcom/vulkan/v3dv_private.h | 30 +++
5 files changed, 619 insertions(+)
diff --git a/src/broadcom/vulkan/meson.build b/src/broadcom/vulkan/meson.build
index bfa7e9f29f2..f86598ee95e 100644
--- a/src/broadcom/vulkan/meson.build
+++ b/src/broadcom/vulkan/meson.build
@@ -98,6 +98,12 @@ if with_platform_wayland
libv3dv_files += [wayland_drm_client_protocol_h, wayland_drm_protocol_c]
endif
+if with_platform_android
+ v3dv_deps += dep_android
+ v3dv_flags += '-DVK_USE_PLATFORM_ANDROID_KHR'
+ libv3dv_files += files('v3dv_android.c')
+endif
+
per_version_libs = []
foreach ver : v3d_versions
per_version_libs += static_library(
diff --git a/src/broadcom/vulkan/v3dv_android.c b/src/broadcom/vulkan/v3dv_android.c
new file mode 100644
index 00000000000..7ebc5a01adc
--- /dev/null
+++ b/src/broadcom/vulkan/v3dv_android.c
@@ -0,0 +1,539 @@
+/*
+ * Copyright © 2017, Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "v3dv_private.h"
+#include <hardware/gralloc.h>
+
+#if ANDROID_API_LEVEL >= 26
+#include <hardware/gralloc1.h>
+#endif
+
+#include "drm-uapi/drm_fourcc.h"
+#include <hardware/hardware.h>
+#include <hardware/hwvulkan.h>
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vk_icd.h>
+
+#include "util/libsync.h"
+#include "util/log.h"
+#include "util/os_file.h"
+
+static int
+v3dv_hal_open(const struct hw_module_t *mod,
+ const char *id,
+ struct hw_device_t **dev);
+static int
+v3dv_hal_close(struct hw_device_t *dev);
+
+static void UNUSED
+static_asserts(void)
+{
+ STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
+}
+
+PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
+ .id = HWVULKAN_HARDWARE_MODULE_ID,
+ .name = "Broadcom Vulkan HAL",
+ .author = "Mesa3D",
+ .methods =
+ &(hw_module_methods_t) {
+ .open = v3dv_hal_open,
+ },
+ },
+};
+
+/* If any bits in test_mask are set, then unset them and return true. */
+static inline bool
+unmask32(uint32_t *inout_mask, uint32_t test_mask)
+{
+ uint32_t orig_mask = *inout_mask;
+ *inout_mask &= ~test_mask;
+ return *inout_mask != orig_mask;
+}
+
+static int
+v3dv_hal_open(const struct hw_module_t *mod,
+ const char *id,
+ struct hw_device_t **dev)
+{
+ assert(mod == &HAL_MODULE_INFO_SYM.common);
+ assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
+
+ hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
+ if (!hal_dev)
+ return -1;
+
+ *hal_dev = (hwvulkan_device_t){
+ .common =
+ {
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+ .module = &HAL_MODULE_INFO_SYM.common,
+ .close = v3dv_hal_close,
+ },
+ .EnumerateInstanceExtensionProperties =
+ v3dv_EnumerateInstanceExtensionProperties,
+ .CreateInstance = v3dv_CreateInstance,
+ .GetInstanceProcAddr = v3dv_GetInstanceProcAddr,
+ };
+
+ mesa_logi("v3dv: Warning: Android Vulkan implementation is experimental");
+
+ *dev = &hal_dev->common;
+ return 0;
+}
+
+static int
+v3dv_hal_close(struct hw_device_t *dev)
+{
+ /* hwvulkan.h claims that hw_device_t::close() is never called. */
+ return -1;
+}
+
+static int
+get_format_bpp(int native)
+{
+ int bpp;
+
+ switch (native) {
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ bpp = 8;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ bpp = 2;
+ break;
+ default:
+ bpp = 0;
+ break;
+ }
+
+ return bpp;
+}
+
+/* get buffer info from VkNativeBufferANDROID */
+static VkResult
+v3dv_gralloc_info_other(struct v3dv_device *device,
+ const VkNativeBufferANDROID *native_buffer,
+ int *out_stride,
+ uint64_t *out_modifier)
+{
+ *out_stride = native_buffer->stride /*in pixels*/ *
+ get_format_bpp(native_buffer->format);
+ *out_modifier = DRM_FORMAT_MOD_LINEAR;
+ return VK_SUCCESS;
+}
+
+static const char cros_gralloc_module_name[] = "CrOS Gralloc";
+
+#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
+
+struct cros_gralloc0_buffer_info
+{
+ uint32_t drm_fourcc;
+ int num_fds;
+ int fds[4];
+ uint64_t modifier;
+ int offset[4];
+ int stride[4];
+};
+
+static VkResult
+v3dv_gralloc_info_cros(struct v3dv_device *device,
+ const VkNativeBufferANDROID *native_buffer,
+ int *out_stride,
+ uint64_t *out_modifier)
+{
+ const gralloc_module_t *gralloc = device->gralloc;
+ struct cros_gralloc0_buffer_info info;
+ int ret;
+
+ ret = gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO,
+ native_buffer->handle, &info);
+ if (ret)
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+
+ *out_stride = info.stride[0];
+ *out_modifier = info.modifier;
+
+ return VK_SUCCESS;
+}
+
+VkResult
+v3dv_gralloc_info(struct v3dv_device *device,
+ const VkNativeBufferANDROID *native_buffer,
+ int *out_dmabuf,
+ int *out_stride,
+ int *out_size,
+ uint64_t *out_modifier)
+{
+ if (device->gralloc_type == V3DV_GRALLOC_UNKNOWN) {
+ /* get gralloc module for gralloc buffer info query */
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **) &device->gralloc);
+
+ device->gralloc_type = V3DV_GRALLOC_OTHER;
+
+ if (err == 0) {
+ const gralloc_module_t *gralloc = device->gralloc;
+ mesa_logi("opened gralloc module name: %s", gralloc->common.name);
+
+ if (strcmp(gralloc->common.name, cros_gralloc_module_name) == 0 &&
+ gralloc->perform) {
+ device->gralloc_type = V3DV_GRALLOC_CROS;
+ }
+ }
+ }
+
+ *out_dmabuf = native_buffer->handle->data[0];
+ *out_size = lseek(*out_dmabuf, 0, SEEK_END);
+
+ if (device->gralloc_type == V3DV_GRALLOC_CROS) {
+ return v3dv_gralloc_info_cros(device, native_buffer, out_stride,
+ out_modifier);
+ } else {
+ return v3dv_gralloc_info_other(device, native_buffer, out_stride,
+ out_modifier);
+ }
+}
+
+VkResult
+v3dv_import_native_buffer_fd(VkDevice device_h,
+ int native_buffer_fd,
+ const VkAllocationCallbacks *alloc,
+ VkImage image_h)
+{
+ struct v3dv_image *image = NULL;
+ VkResult result;
+
+ image = v3dv_image_from_handle(image_h);
+
+ VkDeviceMemory memory_h;
+
+ const VkMemoryDedicatedAllocateInfo ded_alloc = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = NULL,
+ .buffer = VK_NULL_HANDLE,
+ .image = image_h
+ };
+
+ const VkImportMemoryFdInfoKHR import_info = {
+ .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
+ .pNext = &ded_alloc,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
+ .fd = os_dupfd_cloexec(native_buffer_fd),
+ };
+
+ result =
+ v3dv_AllocateMemory(device_h,
+ &(VkMemoryAllocateInfo) {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &import_info,
+ .allocationSize = image->size,
+ .memoryTypeIndex = 0,
+ },
+ alloc, &memory_h);
+
+ if (result != VK_SUCCESS)
+ goto fail_create_image;
+
+ VkBindImageMemoryInfo bind_info = {
+ .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
+ .image = image_h,
+ .memory = memory_h,
+ .memoryOffset = 0,
+ };
+ v3dv_BindImageMemory2(device_h, 1, &bind_info);
+
+ image->is_native_buffer_memory = true;
+
+ return VK_SUCCESS;
+
+fail_create_image:
+ close(import_info.fd);
+
+ return result;
+}
+
+static VkResult
+format_supported_with_usage(VkDevice device_h,
+ VkFormat format,
+ VkImageUsageFlags imageUsage)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, device_h);
+ struct v3dv_physical_device *phys_dev = &device->instance->physicalDevice;
+ VkPhysicalDevice phys_dev_h = v3dv_physical_device_to_handle(phys_dev);
+ VkResult result;
+
+ const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ .format = format,
+ .type = VK_IMAGE_TYPE_2D,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = imageUsage,
+ };
+
+ VkImageFormatProperties2 image_format_props = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+ };
+
+ /* Check that requested format and usage are supported. */
+ result = v3dv_GetPhysicalDeviceImageFormatProperties2(
+ phys_dev_h, &image_format_info, &image_format_props);
+ if (result != VK_SUCCESS) {
+ return vk_errorf(device, result,
+ "v3dv_GetPhysicalDeviceImageFormatProperties2 failed "
+ "inside %s",
+ __func__);
+ }
+
+ return VK_SUCCESS;
+}
+
+static VkResult
+setup_gralloc0_usage(struct v3dv_device *device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int *grallocUsage)
+{
+ if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
+ *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
+
+ if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_STORAGE_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
+ *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
+
+ /* All VkImageUsageFlags not explicitly checked here are unsupported for
+ * gralloc swapchains.
+ */
+ if (imageUsage != 0) {
+ return vk_errorf(device, VK_ERROR_FORMAT_NOT_SUPPORTED,
+ "unsupported VkImageUsageFlags(0x%x) for gralloc "
+ "swapchain",
+ imageUsage);
+ }
+
+ /* Swapchain assumes direct displaying, therefore enable COMPOSER flag,
+ * In case format is not supported by display controller, gralloc will
+ * drop this flag and still allocate the buffer in VRAM
+ */
+ *grallocUsage |= GRALLOC_USAGE_HW_COMPOSER;
+
+ if (*grallocUsage == 0)
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+v3dv_GetSwapchainGrallocUsageANDROID(VkDevice device_h,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int *grallocUsage)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, device_h);
+ VkResult result;
+
+ result = format_supported_with_usage(device_h, format, imageUsage);
+ if (result != VK_SUCCESS)
+ return result;
+
+ *grallocUsage = 0;
+ return setup_gralloc0_usage(device, format, imageUsage, grallocUsage);
+}
+
+#if ANDROID_API_LEVEL >= 26
+VKAPI_ATTR VkResult VKAPI_CALL
+v3dv_GetSwapchainGrallocUsage2ANDROID(
+ VkDevice device_h,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+ uint64_t *grallocConsumerUsage,
+ uint64_t *grallocProducerUsage)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, device_h);
+ VkResult result;
+
+ *grallocConsumerUsage = 0;
+ *grallocProducerUsage = 0;
+ mesa_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);
+
+ result = format_supported_with_usage(device_h, format, imageUsage);
+ if (result != VK_SUCCESS)
+ return result;
+
+ int32_t grallocUsage = 0;
+ result = setup_gralloc0_usage(device, format, imageUsage, &grallocUsage);
+ if (result != VK_SUCCESS)
+ return result;
+
+ /* Setup gralloc1 usage flags from gralloc0 flags. */
+
+ if (grallocUsage & GRALLOC_USAGE_HW_RENDER) {
+ *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
+ }
+
+ if (grallocUsage & GRALLOC_USAGE_HW_TEXTURE) {
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+ }
+
+ if (grallocUsage & GRALLOC_USAGE_HW_COMPOSER) {
+ /* GPU composing case */
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+ /* Hardware composing case */
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
+ }
+
+ return VK_SUCCESS;
+}
+#endif
+
+VKAPI_ATTR VkResult VKAPI_CALL
+v3dv_AcquireImageANDROID(VkDevice device_h,
+ VkImage image_h,
+ int nativeFenceFd,
+ VkSemaphore semaphore_h,
+ VkFence fence_h)
+{
+ V3DV_FROM_HANDLE(v3dv_device, device, device_h);
+ VkResult result = VK_SUCCESS;
+
+ /* From https://source.android.com/devices/graphics/implement-vulkan :
+ *
+ * "The driver takes ownership of the fence file descriptor and closes
+ * the fence file descriptor when no longer needed. The driver must do
+ * so even if neither a semaphore or fence object is provided, or even
+ * if vkAcquireImageANDROID fails and returns an error."
+ *
+ * The Vulkan spec for VkImportFence/SemaphoreFdKHR(), however, requires
+ * the file descriptor to be left alone on failure.
+ */
+ int semaphore_fd = -1, fence_fd = -1;
+ if (nativeFenceFd >= 0) {
+ if (semaphore_h != VK_NULL_HANDLE && fence_h != VK_NULL_HANDLE) {
+ /* We have both so we have to import the sync file twice. One of
+ * them needs to be a dup.
+ */
+ semaphore_fd = nativeFenceFd;
+ fence_fd = os_dupfd_cloexec(nativeFenceFd);
+ if (fence_fd < 0) {
+ VkResult err = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
+ : VK_ERROR_OUT_OF_HOST_MEMORY;
+ close(nativeFenceFd);
+ return vk_error(device, err);
+ }
+ } else if (semaphore_h != VK_NULL_HANDLE) {
+ semaphore_fd = nativeFenceFd;
+ } else if (fence_h != VK_NULL_HANDLE) {
+ fence_fd = nativeFenceFd;
+ } else {
+ /* Nothing to import into so we have to close the file */
+ close(nativeFenceFd);
+ }
+ }
+
+ if (semaphore_h != VK_NULL_HANDLE) {
+ const VkImportSemaphoreFdInfoKHR info = {
+ .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
+ .semaphore = semaphore_h,
+ .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
+ .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+ .fd = semaphore_fd,
+ };
+ result = v3dv_ImportSemaphoreFdKHR(device_h, &info);
+ if (result == VK_SUCCESS)
+ semaphore_fd = -1; /* VK took ownership */
+ }
+
+ if (result == VK_SUCCESS && fence_h != VK_NULL_HANDLE) {
+ const VkImportFenceFdInfoKHR info = {
+ .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
+ .fence = fence_h,
+ .flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
+ .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
+ .fd = fence_fd,
+ };
+ result = v3dv_ImportFenceFdKHR(device_h, &info);
+ if (result == VK_SUCCESS)
+ fence_fd = -1; /* VK took ownership */
+ }
+
+ if (semaphore_fd >= 0)
+ close(semaphore_fd);
+ if (fence_fd >= 0)
+ close(fence_fd);
+
+ return result;
+}
+
+VkResult
+v3dv_QueueSignalReleaseImageANDROID(VkQueue queue,
+ uint32_t waitSemaphoreCount,
+ const VkSemaphore *pWaitSemaphores,
+ VkImage image,
+ int *pNativeFenceFd)
+{
+ VkResult result;
+
+ if (waitSemaphoreCount == 0)
+ goto done;
+
+ result = v3dv_QueueSubmit(
+ queue, 1,
+ &(VkSubmitInfo) {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = pWaitSemaphores,
+ .pWaitDstStageMask =
+ &(VkPipelineStageFlags) { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT },
+ },
+ (VkFence) VK_NULL_HANDLE);
+ if (result != VK_SUCCESS)
+ return result;
+
+done:
+ if (pNativeFenceFd) {
+ /* We can rely implicit on sync because above we submitted all
+ * semaphores to the queue.
+ */
+ *pNativeFenceFd = -1;
+ }
+
+ return VK_SUCCESS;
+}
diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c
index 2ab2ccb90ac..8d17320c652 100644
--- a/src/broadcom/vulkan/v3dv_device.c
+++ b/src/broadcom/vulkan/v3dv_device.c
@@ -155,6 +155,9 @@ get_device_extensions(const struct v3dv_physical_device *device,
.EXT_private_data = true,
.EXT_provoking_vertex = true,
.EXT_vertex_attribute_divisor = true,
+#ifdef ANDROID
+ .ANDROID_native_buffer = true,
+#endif
};
}
diff --git a/src/broadcom/vulkan/v3dv_image.c b/src/broadcom/vulkan/v3dv_image.c
index 06ecb2bfa12..395a7f467fa 100644
--- a/src/broadcom/vulkan/v3dv_image.c
+++ b/src/broadcom/vulkan/v3dv_image.c
@@ -296,6 +296,27 @@ create_image(struct v3dv_device *device,
tiling = VK_IMAGE_TILING_LINEAR;
}
+#ifdef ANDROID
+ const VkNativeBufferANDROID *native_buffer =
+ vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
+
+ int native_buf_fd = -1;
+ int native_buf_stride = 0;
+ int native_buf_size = 0;
+
+ if (native_buffer != NULL) {
+ VkResult result = v3dv_gralloc_info(device, native_buffer, &native_buf_fd,
+ &native_buf_stride, &native_buf_size, &modifier);
+ if (result != VK_SUCCESS) {
+ vk_image_destroy(&device->vk, pAllocator, &image->vk);
+ return result;
+ }
+
+ if (modifier != DRM_FORMAT_MOD_BROADCOM_UIF)
+ tiling = VK_IMAGE_TILING_LINEAR;
+ }
+#endif
+
const struct v3dv_format *format =
v3dv_X(device, get_format)(pCreateInfo->format);
v3dv_assert(format != NULL && format->supported);
@@ -320,6 +341,21 @@ create_image(struct v3dv_device *device,
v3d_setup_slices(image);
+#ifdef ANDROID
+ if (native_buffer != NULL) {
+ image->slices[0].stride = native_buf_stride;
+ image->slices[0].size = image->size = native_buf_size;
+
+ VkResult result = v3dv_import_native_buffer_fd(v3dv_device_to_handle(device),
+ native_buf_fd, pAllocator,
+ v3dv_image_to_handle(image));
+ if (result != VK_SUCCESS) {
+ vk_object_free(&device->vk, pAllocator, image);
+ return result;
+ }
+ }
+#endif
+
*pImage = v3dv_image_to_handle(image);
return VK_SUCCESS;
@@ -435,6 +471,11 @@ v3dv_DestroyImage(VkDevice _device,
if (image == NULL)
return;
+#ifdef ANDROID
+ if (image->is_native_buffer_memory)
+ v3dv_FreeMemory(_device, v3dv_device_memory_to_handle(image->mem), pAllocator);
+#endif
+
vk_image_destroy(&device->vk, pAllocator, &image->vk);
}
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 9636c3f2c47..71068d52253 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -471,6 +471,15 @@ struct v3dv_device {
*/
struct v3dv_bo *default_attribute_float;
VkPhysicalDeviceFeatures features;
+
+#ifdef ANDROID
+ const void *gralloc;
+ enum {
+ V3DV_GRALLOC_UNKNOWN,
+ V3DV_GRALLOC_CROS,
+ V3DV_GRALLOC_OTHER,
+ } gralloc_type;
+#endif
};
struct v3dv_device_memory {
@@ -536,6 +545,11 @@ struct v3dv_image {
struct v3dv_device_memory *mem;
VkDeviceSize mem_offset;
uint32_t alignment;
+
+#ifdef ANDROID
+ /* Image is backed by VK_ANDROID_native_buffer, */
+ bool is_native_buffer_memory;
+#endif
};
VkImageViewType v3dv_image_type_to_view_type(VkImageType type);
@@ -2157,4 +2171,20 @@ u64_compare(const void *key1, const void *key2)
# undef v3dX
#endif
+#ifdef ANDROID
+VkResult
+v3dv_gralloc_info(struct v3dv_device *device,
+ const VkNativeBufferANDROID *gralloc_info,
+ int *out_dmabuf,
+ int *out_stride,
+ int *out_size,
+ uint64_t *out_modifier);
+
+VkResult
+v3dv_import_native_buffer_fd(VkDevice device_h,
+ int dma_buf,
+ const VkAllocationCallbacks *alloc,
+ VkImage image_h);
+#endif /* ANDROID */
+
#endif /* V3DV_PRIVATE_H */
More information about the mesa-commit
mailing list