static VkResult x11_swapchain_destroy(struct wsi_swapchain *anv_chain, const VkAllocationCallbacks *pAllocator) { struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; xcb_void_cookie_t cookie; for (uint32_t i = 0; i < chain->image_count; i++) x11_image_finish(chain, pAllocator, &chain->images[i]); if (chain->threaded) { chain->status = VK_ERROR_OUT_OF_DATE_KHR; /* Push a UINT32_MAX to wake up the manager */ wsi_queue_push(&chain->present_queue, UINT32_MAX); pthread_join(chain->queue_manager, NULL); wsi_queue_destroy(&chain->acquire_queue); wsi_queue_destroy(&chain->present_queue); } xcb_unregister_for_special_event(chain->conn, chain->special_event); cookie = xcb_present_select_input_checked(chain->conn, chain->event_id, chain->window, XCB_PRESENT_EVENT_MASK_NO_EVENT); xcb_discard_reply(chain->conn, cookie.sequence); vk_free(pAllocator, chain); return VK_SUCCESS; }
static struct wsi_x11_connection * wsi_x11_connection_create(const VkAllocationCallbacks *alloc, xcb_connection_t *conn) { xcb_query_extension_cookie_t dri3_cookie, pres_cookie; xcb_query_extension_reply_t *dri3_reply, *pres_reply; struct wsi_x11_connection *wsi_conn = vk_alloc(alloc, sizeof(*wsi_conn), 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!wsi_conn) return NULL; dri3_cookie = xcb_query_extension(conn, 4, "DRI3"); pres_cookie = xcb_query_extension(conn, 7, "PRESENT"); dri3_reply = xcb_query_extension_reply(conn, dri3_cookie, NULL); pres_reply = xcb_query_extension_reply(conn, pres_cookie, NULL); if (dri3_reply == NULL || pres_reply == NULL) { free(dri3_reply); free(pres_reply); vk_free(alloc, wsi_conn); return NULL; } wsi_conn->has_dri3 = dri3_reply->present != 0; wsi_conn->has_present = pres_reply->present != 0; free(dri3_reply); free(pres_reply); return wsi_conn; }
void tu_pipeline_cache_finish(struct tu_pipeline_cache *cache) { for (unsigned i = 0; i < cache->table_size; ++i) if (cache->hash_table[i]) { vk_free(&cache->alloc, cache->hash_table[i]); } pthread_mutex_destroy(&cache->mutex); free(cache->hash_table); }
VkResult wsi_x11_init_wsi(struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc) { struct wsi_x11 *wsi; VkResult result; wsi = vk_alloc(alloc, sizeof(*wsi), 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (!wsi) { result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail; } int ret = pthread_mutex_init(&wsi->mutex, NULL); if (ret != 0) { if (ret == ENOMEM) { result = VK_ERROR_OUT_OF_HOST_MEMORY; } else { /* FINISHME: Choose a better error. */ result = VK_ERROR_OUT_OF_HOST_MEMORY; } goto fail_alloc; } wsi->connections = _mesa_hash_table_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); if (!wsi->connections) { result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail_mutex; } wsi->base.get_support = x11_surface_get_support; wsi->base.get_capabilities = x11_surface_get_capabilities; wsi->base.get_formats = x11_surface_get_formats; wsi->base.get_present_modes = x11_surface_get_present_modes; wsi->base.create_swapchain = x11_surface_create_swapchain; wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = &wsi->base; wsi_device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = &wsi->base; return VK_SUCCESS; fail_mutex: pthread_mutex_destroy(&wsi->mutex); fail_alloc: vk_free(alloc, wsi); fail: wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB] = NULL; wsi_device->wsi[VK_ICD_WSI_PLATFORM_XLIB] = NULL; return result; }
void wsi_x11_finish_wsi(struct wsi_device *wsi_device, const VkAllocationCallbacks *alloc) { struct wsi_x11 *wsi = (struct wsi_x11 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_XCB]; if (wsi) { struct hash_entry *entry; hash_table_foreach(wsi->connections, entry) wsi_x11_connection_destroy(alloc, entry->data); _mesa_hash_table_destroy(wsi->connections, NULL); pthread_mutex_destroy(&wsi->mutex); vk_free(alloc, wsi); } }
static void wsi_x11_connection_destroy(const VkAllocationCallbacks *alloc, struct wsi_x11_connection *conn) { vk_free(alloc, conn); }
static VkResult x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, VkDevice device, struct wsi_device *wsi_device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks* pAllocator, const struct wsi_image_fns *image_fns, struct wsi_swapchain **swapchain_out) { struct x11_swapchain *chain; xcb_void_cookie_t cookie; VkResult result; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR); const unsigned num_images = pCreateInfo->minImageCount; size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]); chain = vk_alloc(pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (chain == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY; xcb_connection_t *conn = x11_surface_get_connection(icd_surface); xcb_window_t window = x11_surface_get_window(icd_surface); xcb_get_geometry_reply_t *geometry = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), NULL); if (geometry == NULL) return VK_ERROR_SURFACE_LOST_KHR; chain->base.device = device; chain->base.destroy = x11_swapchain_destroy; chain->base.get_images = x11_get_images; chain->base.acquire_next_image = x11_acquire_next_image; chain->base.queue_present = x11_queue_present; chain->base.image_fns = image_fns; chain->base.present_mode = pCreateInfo->presentMode; chain->conn = conn; chain->window = window; chain->depth = geometry->depth; chain->extent = pCreateInfo->imageExtent; chain->image_count = num_images; chain->send_sbc = 0; chain->last_present_msc = 0; chain->threaded = false; chain->status = VK_SUCCESS; free(geometry); chain->event_id = xcb_generate_id(chain->conn); xcb_present_select_input(chain->conn, chain->event_id, chain->window, XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY | XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY | XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY); /* Create an XCB event queue to hold present events outside of the usual * application event queue */ chain->special_event = xcb_register_for_special_xge(chain->conn, &xcb_present_id, chain->event_id, NULL); chain->gc = xcb_generate_id(chain->conn); if (!chain->gc) { /* FINISHME: Choose a better error. */ result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail_register; } cookie = xcb_create_gc(chain->conn, chain->gc, chain->window, XCB_GC_GRAPHICS_EXPOSURES, (uint32_t []) { 0 }); xcb_discard_reply(chain->conn, cookie.sequence); uint32_t image = 0; for (; image < chain->image_count; image++) { result = x11_image_init(device, chain, pCreateInfo, pAllocator, &chain->images[image]); if (result != VK_SUCCESS) goto fail_init_images; } if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) { chain->threaded = true; /* Initialize our queues. We make them image_count + 1 because we will * occasionally use UINT32_MAX to signal the other thread that an error * has occurred and we don't want an overflow. */ int ret; ret = wsi_queue_init(&chain->acquire_queue, chain->image_count + 1); if (ret) { goto fail_init_images; } ret = wsi_queue_init(&chain->present_queue, chain->image_count + 1); if (ret) { wsi_queue_destroy(&chain->acquire_queue); goto fail_init_images; } for (unsigned i = 0; i < chain->image_count; i++) wsi_queue_push(&chain->acquire_queue, i); ret = pthread_create(&chain->queue_manager, NULL, x11_manage_fifo_queues, chain); if (ret) { wsi_queue_destroy(&chain->present_queue); wsi_queue_destroy(&chain->acquire_queue); goto fail_init_images; } } *swapchain_out = &chain->base; return VK_SUCCESS; fail_init_images: for (uint32_t j = 0; j < image; j++) x11_image_finish(chain, pAllocator, &chain->images[j]); fail_register: xcb_unregister_for_special_event(chain->conn, chain->special_event); vk_free(pAllocator, chain); return result; }