*/
#include <hardware/gralloc.h>
+
+#if ANDROID_API_LEVEL >= 26
+#include <hardware/gralloc1.h>
+#endif
+
#include <hardware/hardware.h>
#include <hardware/hwvulkan.h>
#include <vulkan/vk_android_native_buffer.h>
return -1;
}
+#if ANDROID_API_LEVEL >= 26
static VkResult
get_ahw_buffer_format_properties(
VkDevice device_h,
* one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
*/
if (!(desc.usage & (gpu_usage)))
- return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
/* Fill properties fields based on description. */
VkAndroidHardwareBufferFormatPropertiesANDROID *p = pProperties;
- p->format = vk_format_from_android(desc.format);
+ p->format = vk_format_from_android(desc.format, desc.usage);
const struct anv_format *anv_format = anv_get_format(p->format);
p->externalFormat = (uint64_t) (uintptr_t) anv_format;
VkAndroidHardwareBufferPropertiesANDROID *pProperties)
{
ANV_FROM_HANDLE(anv_device, dev, device_h);
- struct anv_physical_device *pdevice = &dev->instance->physicalDevice;
VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop =
vk_find_struct(pProperties->pNext,
AHardwareBuffer_getNativeHandle(buffer);
int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
if (dma_buf < 0)
- return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
/* All memory types. */
- uint32_t memory_types = (1ull << pdevice->memory.type_count) - 1;
+ uint32_t memory_types = (1ull << dev->physical->memory.type_count) - 1;
pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END);
pProperties->memoryTypeBits = memory_types;
return VK_SUCCESS;
}
+VkResult
+anv_GetMemoryAndroidHardwareBufferANDROID(
+ VkDevice device_h,
+ const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
+ struct AHardwareBuffer **pBuffer)
+{
+ ANV_FROM_HANDLE(anv_device_memory, mem, pInfo->memory);
+
+ /* Some quotes from Vulkan spec:
+ *
+ * "If the device memory was created by importing an Android hardware
+ * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
+ * Android hardware buffer object."
+ *
+ * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
+ * have been included in VkExportMemoryAllocateInfo::handleTypes when
+ * memory was created."
+ */
+ if (mem->ahw) {
+ *pBuffer = mem->ahw;
+ /* Increase refcount. */
+ AHardwareBuffer_acquire(mem->ahw);
+ return VK_SUCCESS;
+ }
+
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+#endif
+
/* Construct ahw usage mask from image usage bits, see
* 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
*/
const VkImageUsageFlags vk_usage)
{
uint64_t ahw_usage = 0;
-
+#if ANDROID_API_LEVEL >= 26
if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
/* No usage bits set - set at least one GPU usage. */
if (ahw_usage == 0)
ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
-
+#endif
return ahw_usage;
}
-VkResult
-anv_GetMemoryAndroidHardwareBufferANDROID(
- VkDevice device_h,
- const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
- struct AHardwareBuffer **pBuffer)
-{
- ANV_FROM_HANDLE(anv_device_memory, mem, pInfo->memory);
-
- /* Some quotes from Vulkan spec:
- *
- * "If the device memory was created by importing an Android hardware
- * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
- * Android hardware buffer object."
- *
- * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
- * have been included in VkExportMemoryAllocateInfoKHR::handleTypes when
- * memory was created."
- */
- if (mem->ahw) {
- *pBuffer = mem->ahw;
- /* Increase refcount. */
- AHardwareBuffer_acquire(mem->ahw);
- return VK_SUCCESS;
- }
-
- return VK_ERROR_OUT_OF_HOST_MEMORY;
-}
-
/*
* Called from anv_AllocateMemory when import AHardwareBuffer.
*/
struct anv_device_memory *mem,
const VkImportAndroidHardwareBufferInfoANDROID *info)
{
+#if ANDROID_API_LEVEL >= 26
ANV_FROM_HANDLE(anv_device, device, device_h);
/* Import from AHardwareBuffer to anv_device_memory. */
*/
int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
if (dma_buf < 0)
- return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
-
- uint64_t bo_flags = ANV_BO_EXTERNAL;
- if (device->instance->physicalDevice.supports_48bit_addresses)
- bo_flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
- if (device->instance->physicalDevice.use_softpin)
- bo_flags |= EXEC_OBJECT_PINNED;
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
- VkResult result = anv_bo_cache_import(device, &device->bo_cache,
- dma_buf, bo_flags, &mem->bo);
- assert(VK_SUCCESS);
+ VkResult result = anv_device_import_bo(device, dma_buf, 0,
+ 0 /* client_address */,
+ &mem->bo);
+ assert(result == VK_SUCCESS);
/* "If the vkAllocateMemory command succeeds, the implementation must
* acquire a reference to the imported hardware buffer, which it must
mem->ahw = info->buffer;
return VK_SUCCESS;
+#else
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
}
VkResult
struct anv_device_memory *mem,
const VkMemoryAllocateInfo *pAllocateInfo)
{
+#if ANDROID_API_LEVEL >= 26
ANV_FROM_HANDLE(anv_device, dev, device_h);
const VkMemoryDedicatedAllocateInfo *dedicated_info =
return VK_ERROR_OUT_OF_HOST_MEMORY;
mem->ahw = ahw;
+ return VK_SUCCESS;
+#else
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+
+}
+
+VkResult
+anv_image_from_external(
+ VkDevice device_h,
+ const VkImageCreateInfo *base_info,
+ const VkExternalMemoryImageCreateInfo *create_info,
+ const VkAllocationCallbacks *alloc,
+ VkImage *out_image_h)
+{
+#if ANDROID_API_LEVEL >= 26
+ ANV_FROM_HANDLE(anv_device, device, device_h);
+
+ const VkExternalFormatANDROID *ext_info =
+ vk_find_struct_const(base_info->pNext, EXTERNAL_FORMAT_ANDROID);
+
+ if (ext_info && ext_info->externalFormat != 0) {
+ assert(base_info->format == VK_FORMAT_UNDEFINED);
+ assert(base_info->imageType == VK_IMAGE_TYPE_2D);
+ assert(base_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT);
+ assert(base_info->tiling == VK_IMAGE_TILING_OPTIMAL);
+ }
+
+ struct anv_image_create_info anv_info = {
+ .vk_info = base_info,
+ .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT,
+ .external_format = true,
+ };
+
+ VkImage image_h;
+ VkResult result = anv_image_create(device_h, &anv_info, alloc, &image_h);
+ if (result != VK_SUCCESS)
+ return result;
+
+ *out_image_h = image_h;
return VK_SUCCESS;
+#else
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
}
+
VkResult
anv_image_from_gralloc(VkDevice device_h,
const VkImageCreateInfo *base_info,
};
if (gralloc_info->handle->numFds != 1) {
- return vk_errorf(device->instance, device,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ return vk_errorf(device, device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
"VkNativeBufferANDROID::handle::numFds is %d, "
"expected 1", gralloc_info->handle->numFds);
}
*/
int dma_buf = gralloc_info->handle->data[0];
- uint64_t bo_flags = ANV_BO_EXTERNAL;
- if (device->instance->physicalDevice.supports_48bit_addresses)
- bo_flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
- if (device->instance->physicalDevice.use_softpin)
- bo_flags |= EXEC_OBJECT_PINNED;
-
- result = anv_bo_cache_import(device, &device->bo_cache, dma_buf, bo_flags, &bo);
+ /* We need to set the WRITE flag on window system buffers so that GEM will
+ * know we're writing to them and synchronize uses on other rings (for
+ * example, if the display server uses the blitter ring).
+ *
+ * If this function fails and if the imported bo was resident in the cache,
+ * we should avoid updating the bo's flags. Therefore, we defer updating
+ * the flags until success is certain.
+ *
+ */
+ result = anv_device_import_bo(device, dma_buf,
+ ANV_BO_ALLOC_IMPLICIT_SYNC |
+ ANV_BO_ALLOC_IMPLICIT_WRITE,
+ 0 /* client_address */,
+ &bo);
if (result != VK_SUCCESS) {
- return vk_errorf(device->instance, device, result,
+ return vk_errorf(device, device, result,
"failed to import dma-buf from VkNativeBufferANDROID");
}
anv_info.isl_tiling_flags = ISL_TILING_Y0_BIT;
break;
case -1:
- result = vk_errorf(device->instance, device,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ result = vk_errorf(device, device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
"DRM_IOCTL_I915_GEM_GET_TILING failed for "
"VkNativeBufferANDROID");
goto fail_tiling;
default:
- result = vk_errorf(device->instance, device,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ result = vk_errorf(device, device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
"DRM_IOCTL_I915_GEM_GET_TILING returned unknown "
"tiling %d for VkNativeBufferANDROID", i915_tiling);
goto fail_tiling;
goto fail_create;
if (bo->size < image->size) {
- result = vk_errorf(device->instance, device,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ result = vk_errorf(device, device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
"dma-buf from VkNativeBufferANDROID is too small for "
"VkImage: %"PRIu64"B < %"PRIu64"B",
bo->size, image->size);
image->planes[0].address.bo = bo;
image->planes[0].bo_is_owned = true;
- /* We need to set the WRITE flag on window system buffers so that GEM will
- * know we're writing to them and synchronize uses on other rings (for
- * example, if the display server uses the blitter ring).
- *
- * If this function fails and if the imported bo was resident in the cache,
- * we should avoid updating the bo's flags. Therefore, we defer updating
- * the flags until success is certain.
- *
- */
- bo->flags &= ~EXEC_OBJECT_ASYNC;
- bo->flags |= EXEC_OBJECT_WRITE;
-
/* Don't clobber the out-parameter until success is certain. */
*out_image_h = image_h;
anv_DestroyImage(device_h, image_h, alloc);
fail_create:
fail_tiling:
- anv_bo_cache_release(device, &device->bo_cache, bo);
+ anv_device_release_bo(device, bo);
return result;
}
-VkResult anv_GetSwapchainGrallocUsageANDROID(
- VkDevice device_h,
- VkFormat format,
- VkImageUsageFlags imageUsage,
- int* grallocUsage)
+static VkResult
+format_supported_with_usage(VkDevice device_h, VkFormat format,
+ VkImageUsageFlags imageUsage)
{
ANV_FROM_HANDLE(anv_device, device, device_h);
- struct anv_physical_device *phys_dev = &device->instance->physicalDevice;
- VkPhysicalDevice phys_dev_h = anv_physical_device_to_handle(phys_dev);
+ VkPhysicalDevice phys_dev_h = anv_physical_device_to_handle(device->physical);
VkResult result;
- *grallocUsage = 0;
- intel_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);
-
- /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
- * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags.
- * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
- *
- * TODO(jessehall): I think these are right, but haven't thought hard
- * about it. Do we need to query the driver for support of any of
- * these?
- *
- * Any disagreement between this function and the hardcoded
- * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
- * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
- */
-
- const VkPhysicalDeviceImageFormatInfo2KHR image_format_info = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
+ 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,
};
- VkImageFormatProperties2KHR image_format_props = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
+ VkImageFormatProperties2 image_format_props = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
};
/* Check that requested format and usage are supported. */
result = anv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h,
&image_format_info, &image_format_props);
if (result != VK_SUCCESS) {
- return vk_errorf(device->instance, device, result,
+ return vk_errorf(device, device, result,
"anv_GetPhysicalDeviceImageFormatProperties2 failed "
"inside %s", __func__);
}
+ return VK_SUCCESS;
+}
- /* Reject STORAGE here to avoid complexity elsewhere. */
- if (imageUsage & VK_IMAGE_USAGE_STORAGE_BIT) {
- return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,
- "VK_IMAGE_USAGE_STORAGE_BIT unsupported for gralloc "
- "swapchain");
- }
+
+static VkResult
+setup_gralloc0_usage(VkFormat format, VkImageUsageFlags imageUsage,
+ int *grallocUsage)
+{
+ /* WARNING: Android's libvulkan.so hardcodes the VkImageUsageFlags
+ * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags.
+ * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
+ *
+ * TODO(jessehall): I think these are right, but haven't thought hard
+ * about it. Do we need to query the driver for support of any of
+ * these?
+ *
+ * Any disagreement between this function and the hardcoded
+ * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
+ * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
+ */
if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
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;
* gralloc swapchains.
*/
if (imageUsage != 0) {
- return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,
+ return vk_errorf(device, device, VK_ERROR_FORMAT_NOT_SUPPORTED,
"unsupported VkImageUsageFlags(0x%x) for gralloc "
"swapchain", imageUsage);
}
*/
switch (format) {
case VK_FORMAT_B8G8R8A8_UNORM:
- case VK_FORMAT_B5G6R5_UNORM_PACK16:
+ case VK_FORMAT_R5G6B5_UNORM_PACK16:
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SRGB:
*grallocUsage |= GRALLOC_USAGE_HW_FB |
return VK_SUCCESS;
}
+#if ANDROID_API_LEVEL >= 26
+VkResult anv_GetSwapchainGrallocUsage2ANDROID(
+ VkDevice device_h,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+ uint64_t* grallocConsumerUsage,
+ uint64_t* grallocProducerUsage)
+{
+ ANV_FROM_HANDLE(anv_device, device, device_h);
+ VkResult result;
+
+ *grallocConsumerUsage = 0;
+ *grallocProducerUsage = 0;
+ intel_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(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;
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
+ }
+
+ if (grallocUsage & GRALLOC_USAGE_HW_TEXTURE) {
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+ }
+
+ if (grallocUsage & (GRALLOC_USAGE_HW_FB |
+ GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_EXTERNAL_DISP)) {
+ *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
+ *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
+ }
+
+ return VK_SUCCESS;
+}
+#endif
+
+VkResult anv_GetSwapchainGrallocUsageANDROID(
+ VkDevice device_h,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int* grallocUsage)
+{
+ VkResult result;
+
+ *grallocUsage = 0;
+ intel_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;
+
+ return setup_gralloc0_usage(format, imageUsage, grallocUsage);
+}
+
VkResult
anv_AcquireImageANDROID(
VkDevice device_h,
* VkFence.
*/
if (sync_wait(nativeFenceFd, /*timeout*/ -1) < 0) {
- result = vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
+ result = vk_errorf(device, device, VK_ERROR_DEVICE_LOST,
"%s: failed to wait on nativeFenceFd=%d",
__func__, nativeFenceFd);
}
result = anv_QueueSubmit(anv_queue_to_handle(&device->queue), 1,
&submit, fence_h);
if (result != VK_SUCCESS) {
- return vk_errorf(device->instance, device, result,
+ return vk_errorf(device, device, result,
"anv_QueueSubmit failed inside %s", __func__);
}
}