From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 59 +++++++++++++++++++++++++++++++++++++-- dlls/winex11.drv/window.c | 20 +++++++++++++ dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index fd4c5168901..d8ffc201afe 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -49,6 +49,8 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
static pthread_mutex_t vulkan_mutex;
+static XContext vulkan_swapchain_context; + #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
static struct list surface_list = LIST_INIT( surface_list ); @@ -72,6 +74,7 @@ typedef struct VkXlibSurfaceCreateInfoKHR Window window; } VkXlibSurfaceCreateInfoKHR;
+static VkResult (*pvkAcquireNextImageKHR)(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t *); static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); static VkResult (*pvkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKHR *, const VkAllocationCallbacks *, VkSwapchainKHR *); static VkResult (*pvkCreateXlibSurfaceKHR)(VkInstance, const VkXlibSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); @@ -115,6 +118,7 @@ static void wine_vk_init(void)
#define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail #define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(vulkan_handle, #f) + LOAD_FUNCPTR(vkAcquireNextImageKHR); LOAD_FUNCPTR(vkCreateInstance); LOAD_FUNCPTR(vkCreateSwapchainKHR); LOAD_FUNCPTR(vkCreateXlibSurfaceKHR); @@ -138,6 +142,7 @@ static void wine_vk_init(void) #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
+ vulkan_swapchain_context = XUniqueContext(); return;
fail: @@ -193,6 +198,13 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo return VK_SUCCESS; }
+static struct wine_vk_surface *wine_vk_surface_grab( struct wine_vk_surface *surface ) +{ + int refcount = InterlockedIncrement( &surface->ref ); + TRACE( "surface %p, refcount %d.\n", surface, refcount ); + return surface; +} + static void wine_vk_surface_release( struct wine_vk_surface *surface ) { int refcount = InterlockedDecrement( &surface->ref ); @@ -312,6 +324,8 @@ static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device, { struct wine_vk_surface *x11_surface = surface_from_handle(create_info->surface); VkSwapchainCreateInfoKHR create_info_host; + VkResult result; + TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain);
if (allocator) @@ -323,7 +337,14 @@ static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device, create_info_host = *create_info; create_info_host.surface = x11_surface->surface;
- return pvkCreateSwapchainKHR(device, &create_info_host, NULL /* allocator */, swapchain); + if ((result = pvkCreateSwapchainKHR( device, &create_info_host, NULL /* allocator */, + swapchain )) == VK_SUCCESS) + { + XSaveContext( gdi_display, (XID)(*swapchain), vulkan_swapchain_context, + (char *)wine_vk_surface_grab( x11_surface ) ); + } + + return result; }
static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, @@ -430,12 +451,17 @@ static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface static void X11DRV_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *allocator) { + struct wine_vk_surface *surface; + TRACE("%p, 0x%s %p\n", device, wine_dbgstr_longlong(swapchain), allocator);
if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
pvkDestroySwapchainKHR(device, swapchain, NULL /* allocator */); + + if (!XFindContext( gdi_display, (XID)swapchain, vulkan_swapchain_context, (char **)&surface )) + wine_vk_surface_release( surface ); }
static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_name, @@ -661,6 +687,33 @@ static VkResult X11DRV_vkGetSwapchainImagesKHR(VkDevice device, return pvkGetSwapchainImagesKHR(device, swapchain, count, images); }
+static VkResult X11DRV_vkAcquireNextImageKHR( VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, + VkSemaphore semaphore, VkFence fence, uint32_t *image_index ) +{ + struct wine_vk_surface *surface; + struct x11drv_win_data *data; + + if (XFindContext( gdi_display, (XID)swapchain, vulkan_swapchain_context, (char **)&surface )) + return VK_ERROR_SURFACE_LOST_KHR; + + if ((data = get_win_data( surface->hwnd ))) + { + attach_client_window( data, surface->window ); + release_win_data( data ); + } + + return pvkAcquireNextImageKHR( device, swapchain, timeout, semaphore, fence, image_index ); +} + +static VkResult X11DRV_vkAcquireNextImage2KHR( VkDevice device, const VkAcquireNextImageInfoKHR *acquire_info, + uint32_t *image_index ) +{ + static int once; + if (!once++) FIXME( "Emulating vkAcquireNextImage2KHR, ignoring pNext.\n" ); + return X11DRV_vkAcquireNextImageKHR( device, acquire_info->swapchain, acquire_info->timeout, + acquire_info->semaphore, acquire_info->fence, image_index ); +} + static VkResult X11DRV_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info) { VkResult res; @@ -704,8 +757,8 @@ static VkSurfaceKHR X11DRV_wine_get_native_surface(VkSurfaceKHR surface)
static const struct vulkan_funcs vulkan_funcs = { - NULL, - NULL, + X11DRV_vkAcquireNextImage2KHR, + X11DRV_vkAcquireNextImageKHR, X11DRV_vkCreateInstance, X11DRV_vkCreateSwapchainKHR, X11DRV_vkCreateWin32SurfaceKHR, diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index b709db79b68..c968b9dff24 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1549,6 +1549,26 @@ Window get_dummy_parent(void) return dummy_parent; }
+/********************************************************************** + * attach_client_window + */ +void attach_client_window( struct x11drv_win_data *data, Window window ) +{ + if (data->client_window == window || !data->whole_window) return; + detach_client_window( data, data->client_window ); + + data->client_window = window; + + XSaveContext( data->display, data->client_window, winContext, (char *)data->hwnd ); + XSelectInput( data->display, data->client_window, ExposureMask ); + XFlush( data->display ); /* make sure XSelectInput is enabled for client_window after this point */ + + XReparentWindow( gdi_display, data->client_window, data->whole_window, + data->client_rect.left - data->whole_rect.left, + data->client_rect.top - data->whole_rect.top ); + TRACE( "%p/%lx attached client window %lx\n", data->hwnd, data->whole_window, data->client_window ); +} +
/********************************************************************** * detach_client_window diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a6406099771..82a1fb062ea 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -659,6 +659,7 @@ extern void make_window_embedded( struct x11drv_win_data *data ) DECLSPEC_HIDDEN extern Window create_dummy_client_window(void) DECLSPEC_HIDDEN; extern Window create_client_window( HWND hwnd, const XVisualInfo *visual ) DECLSPEC_HIDDEN; extern void detach_client_window( struct x11drv_win_data *data, Window window ); +extern void attach_client_window( struct x11drv_win_data *data, Window window ); extern void set_window_visual( struct x11drv_win_data *data, const XVisualInfo *vis, BOOL use_alpha ) DECLSPEC_HIDDEN; extern void change_systray_owner( Display *display, Window systray_window ) DECLSPEC_HIDDEN; extern HWND create_foreign_window( Display *display, Window window ) DECLSPEC_HIDDEN;