From: Rémi Bernon <rbernon(a)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;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/4533