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; }
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; }
VkResult wsi_create_xlib_surface(const VkAllocationCallbacks *pAllocator, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, VkSurfaceKHR *pSurface) { VkIcdSurfaceXlib *surface; surface = vk_alloc(pAllocator, sizeof *surface, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (surface == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY; surface->base.platform = VK_ICD_WSI_PLATFORM_XLIB; surface->dpy = pCreateInfo->dpy; surface->window = pCreateInfo->window; *pSurface = VkIcdSurfaceBase_to_handle(&surface->base); return VK_SUCCESS; }
void tu_pipeline_cache_load(struct tu_pipeline_cache *cache, const void *data, size_t size) { struct tu_device *device = cache->device; struct cache_header header; if (size < sizeof(header)) return; memcpy(&header, data, sizeof(header)); if (header.header_size < sizeof(header)) return; if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE) return; if (header.vendor_id != 0 /* TODO */) return; if (header.device_id != 0 /* TODO */) return; if (memcmp(header.uuid, device->physical_device->cache_uuid, VK_UUID_SIZE) != 0) return; char *end = (void *) data + size; char *p = (void *) data + header.header_size; while (end - p >= sizeof(struct cache_entry)) { struct cache_entry *entry = (struct cache_entry *) p; struct cache_entry *dest_entry; size_t size = entry_size(entry); if (end - p < size) break; dest_entry = vk_alloc(&cache->alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_CACHE); if (dest_entry) { memcpy(dest_entry, entry, size); for (int i = 0; i < MESA_SHADER_STAGES; ++i) dest_entry->variants[i] = NULL; tu_pipeline_cache_add_entry(cache, dest_entry); } p += size; } }
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; }