#include "vk_object.h"
#include "vk_alloc.h"
+#include "util/hash_table.h"
+#include "util/ralloc.h"
void
vk_object_base_init(UNUSED struct vk_device *device,
device->alloc = *instance_alloc;
p_atomic_set(&device->private_data_next_index, 0);
+
+#ifdef ANDROID
+ mtx_init(&device->swapchain_private_mtx, mtx_plain);
+ device->swapchain_private = NULL;
+#endif /* ANDROID */
}
void
vk_device_finish(UNUSED struct vk_device *device)
{
+#ifdef ANDROID
+ if (device->swapchain_private) {
+ hash_table_foreach(device->swapchain_private, entry)
+ util_sparse_array_finish(entry->data);
+ ralloc_free(device->swapchain_private);
+ }
+#endif /* ANDROID */
+
vk_object_base_finish(&device->base);
}
vk_free2(&device->alloc, pAllocator, slot);
}
-static uint64_t *
-vk_object_base_private_data(VkObjectType objectType,
+#ifdef ANDROID
+static VkResult
+get_swapchain_private_data_locked(struct vk_device *device,
+ uint64_t objectHandle,
+ struct vk_private_data_slot *slot,
+ uint64_t **private_data)
+{
+ if (unlikely(device->swapchain_private == NULL)) {
+ /* Even though VkSwapchain is a non-dispatchable object, we know a
+ * priori that Android swapchains are actually pointers so we can use
+ * the pointer hash table for them.
+ */
+ device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
+ if (device->swapchain_private == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ struct hash_entry *entry =
+ _mesa_hash_table_search(device->swapchain_private,
+ (void *)(uintptr_t)objectHandle);
+ if (unlikely(entry == NULL)) {
+ struct util_sparse_array *swapchain_private =
+ ralloc(device->swapchain_private, struct util_sparse_array);
+ util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
+
+ entry = _mesa_hash_table_insert(device->swapchain_private,
+ (void *)(uintptr_t)objectHandle,
+ swapchain_private);
+ if (entry == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ struct util_sparse_array *swapchain_private = entry->data;
+ *private_data = util_sparse_array_get(swapchain_private, slot->index);
+
+ return VK_SUCCESS;
+}
+#endif /* ANDROID */
+
+static VkResult
+vk_object_base_private_data(struct vk_device *device,
+ VkObjectType objectType,
uint64_t objectHandle,
- VkPrivateDataSlotEXT privateDataSlot)
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t **private_data)
{
VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
+
+#ifdef ANDROID
+ /* There is an annoying spec corner here on Android. Because WSI is
+ * implemented in the Vulkan loader which doesn't know about the
+ * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
+ * driver as a special case. On future versions of Android where the
+ * loader does understand VK_EXT_private_data, we'll never see a
+ * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
+ * handle it.
+ */
+ if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
+ mtx_lock(&device->swapchain_private_mtx);
+ VkResult result = get_swapchain_private_data_locked(device, objectHandle,
+ slot, private_data);
+ mtx_unlock(&device->swapchain_private_mtx);
+ return result;
+ }
+#endif /* ANDROID */
+
struct vk_object_base *obj =
vk_object_base_from_u64_handle(objectHandle, objectType);
- return util_sparse_array_get(&obj->private_data, slot->index);
+ *private_data = util_sparse_array_get(&obj->private_data, slot->index);
+
+ return VK_SUCCESS;
}
VkResult
VkPrivateDataSlotEXT privateDataSlot,
uint64_t data)
{
- uint64_t *private_data =
- vk_object_base_private_data(objectType, objectHandle, privateDataSlot);
+ uint64_t *private_data;
+ VkResult result = vk_object_base_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot,
+ &private_data);
+ if (unlikely(result != VK_SUCCESS))
+ return result;
+
*private_data = data;
return VK_SUCCESS;
}
VkPrivateDataSlotEXT privateDataSlot,
uint64_t *pData)
{
- uint64_t *private_data =
- vk_object_base_private_data(objectType, objectHandle, privateDataSlot);
- *pData = *private_data;
+ uint64_t *private_data;
+ VkResult result = vk_object_base_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot,
+ &private_data);
+ if (likely(result == VK_SUCCESS)) {
+ *pData = *private_data;
+ } else {
+ *pData = 0;
+ }
}