This is some preparatory work for vulkan child window and other features which currently live in Proton. I think this could be upstream already, and it will make rebasing patches on top of it simpler. To get vulkan child window upstream we'd probably still need to rework it a bit and maybe try to move the wait and blit to `vkQueuePresent` somehow.
The idea here is also that although Vulkan spec does not allow multiple active swapchains for the same window, Windows tends to allow it especially with D3D, and we also need to support the case where multiple APIs are use to draw onto the same window surface (as we implement D3D on top of GL/Vk for instance).
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 59 ++++++++++++++++++--------------------- dlls/winex11.drv/window.c | 2 +- dlls/winex11.drv/x11drv.h | 2 +- 3 files changed, 29 insertions(+), 34 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 6597771c4c6..005a429f3df 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -49,8 +49,6 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
static pthread_mutex_t vulkan_mutex;
-static XContext vulkan_hwnd_context; - #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
static struct list surface_list = LIST_INIT( surface_list ); @@ -140,7 +138,6 @@ static void wine_vk_init(void) #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
- vulkan_hwnd_context = XUniqueContext(); return;
fail: @@ -196,13 +193,6 @@ 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 ); @@ -232,18 +222,33 @@ static void wine_vk_surface_release( struct wine_vk_surface *surface ) free(surface); }
-void wine_vk_surface_destroy(HWND hwnd) +static void wine_vk_surface_detach( struct wine_vk_surface *surface ) { - struct wine_vk_surface *surface; - pthread_mutex_lock(&vulkan_mutex); - if (!XFindContext(gdi_display, (XID)hwnd, vulkan_hwnd_context, (char **)&surface)) + struct x11drv_win_data *data; + + TRACE( "Detaching surface %p, hwnd %p.\n", surface, surface->hwnd ); + + if (surface->window && (data = get_win_data( surface->hwnd ))) { - surface->hwnd_thread_id = 0; - surface->hwnd = NULL; - wine_vk_surface_release(surface); + detach_client_window( data, surface->window ); + release_win_data( data ); } - XDeleteContext(gdi_display, (XID)hwnd, vulkan_hwnd_context); - pthread_mutex_unlock(&vulkan_mutex); + + surface->hwnd_thread_id = 0; + surface->hwnd = 0; +} + +void destroy_vk_surface( HWND hwnd ) +{ + struct wine_vk_surface *surface, *next; + + pthread_mutex_lock( &vulkan_mutex ); + LIST_FOR_EACH_ENTRY_SAFE( surface, next, &surface_list, struct wine_vk_surface, entry ) + { + if (surface->hwnd != hwnd) continue; + wine_vk_surface_detach( surface ); + } + pthread_mutex_unlock( &vulkan_mutex ); }
void vulkan_thread_detach(void) @@ -254,13 +259,8 @@ void vulkan_thread_detach(void) pthread_mutex_lock(&vulkan_mutex); LIST_FOR_EACH_ENTRY_SAFE(surface, next, &surface_list, struct wine_vk_surface, entry) { - if (surface->hwnd_thread_id != thread_id) - continue; - - TRACE("Detaching surface %p, hwnd %p.\n", surface, surface->hwnd); - XReparentWindow(gdi_display, surface->window, get_dummy_parent(), 0, 0); - XSync(gdi_display, False); - wine_vk_surface_destroy(surface->hwnd); + if (surface->hwnd_thread_id != thread_id) continue; + wine_vk_surface_detach( surface ); } pthread_mutex_unlock(&vulkan_mutex); } @@ -371,11 +371,6 @@ static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance, }
pthread_mutex_lock(&vulkan_mutex); - if (x11_surface->hwnd) - { - wine_vk_surface_destroy( x11_surface->hwnd ); - XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface)); - } list_add_tail(&surface_list, &x11_surface->entry); pthread_mutex_unlock(&vulkan_mutex);
@@ -754,7 +749,7 @@ const struct vulkan_funcs *get_vulkan_driver(UINT version) return NULL; }
-void wine_vk_surface_destroy(HWND hwnd) +void destroy_vk_surface( HWND hwnd ) { }
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index dae60a09af9..f5c62c8e26f 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1867,7 +1867,7 @@ void X11DRV_DestroyWindow( HWND hwnd ) release_win_data( data ); free( data ); destroy_gl_drawable( hwnd ); - wine_vk_surface_destroy( hwnd ); + destroy_vk_surface( hwnd ); }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index dc14d5ff372..caebb115e74 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -646,7 +646,7 @@ extern Window get_dummy_parent(void) DECLSPEC_HIDDEN; extern void sync_gl_drawable( HWND hwnd, BOOL known_child ) DECLSPEC_HIDDEN; extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN; extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN; -extern void wine_vk_surface_destroy( HWND hwnd ) DECLSPEC_HIDDEN; +extern void destroy_vk_surface( HWND hwnd ) DECLSPEC_HIDDEN; extern void vulkan_thread_detach(void) DECLSPEC_HIDDEN;
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 12 +++++++++++- dlls/winex11.drv/window.c | 2 +- dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index f8987e2c49d..6597771c4c6 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -217,7 +217,17 @@ static void wine_vk_surface_release( struct wine_vk_surface *surface ) }
if (surface->window) - XDestroyWindow(gdi_display, surface->window); + { + struct x11drv_win_data *data; + + if ((data = get_win_data( surface->hwnd ))) + { + detach_client_window( data, surface->window ); + release_win_data( data ); + } + + XDestroyWindow( gdi_display, surface->window ); + }
free(surface); } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 4237e92990e..dae60a09af9 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1552,7 +1552,7 @@ Window get_dummy_parent(void) /********************************************************************** * detach_client_window */ -static void detach_client_window( struct x11drv_win_data *data, Window window ) +void detach_client_window( struct x11drv_win_data *data, Window window ) { if (!data->client_window || data->client_window != window) return;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 2c15a95dfab..dc14d5ff372 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -657,6 +657,7 @@ extern void update_net_wm_states( struct x11drv_win_data *data ) DECLSPEC_HIDDEN 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 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;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 53982bb8c3b..4237e92990e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1549,6 +1549,24 @@ Window get_dummy_parent(void) }
+/********************************************************************** + * detach_client_window + */ +static void detach_client_window( struct x11drv_win_data *data, Window window ) +{ + if (!data->client_window || data->client_window != window) return; + + XSelectInput( data->display, data->client_window, 0 ); + XFlush( data->display ); /* make sure XSelectInput is disabled for client_window after this point */ + XDeleteContext( data->display, data->client_window, winContext ); + + XReparentWindow( gdi_display, data->client_window, get_dummy_parent(), 0, 0 ); + TRACE( "%p/%lx detached client window %lx\n", data->hwnd, data->whole_window, data->client_window ); + + data->client_window = 0; +} + + /********************************************************************** * create_dummy_client_window */ @@ -1588,12 +1606,7 @@ Window create_client_window( HWND hwnd, const XVisualInfo *visual ) data->window_rect = data->whole_rect = data->client_rect; }
- if (data->client_window) - { - XDeleteContext( data->display, data->client_window, winContext ); - XReparentWindow( gdi_display, data->client_window, dummy_parent, 0, 0 ); - TRACE( "%p reparent xwin %lx/%lx\n", data->hwnd, data->whole_window, data->client_window ); - } + detach_client_window( data, data->client_window );
if (data->client_colormap) XFreeColormap( gdi_display, data->client_colormap ); data->client_colormap = XCreateColormap( gdi_display, dummy_parent, visual->visual, @@ -1731,12 +1744,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des } else { - if (data->client_window && !already_destroyed) - { - XSelectInput( data->display, data->client_window, 0 ); - XFlush( data->display ); /* make sure XSelectInput doesn't use client_window after this point */ - XReparentWindow( gdi_display, data->client_window, get_dummy_parent(), 0, 0 ); - } + if (!already_destroyed) detach_client_window( data, data->client_window ); XDeleteContext( data->display, data->whole_window, winContext ); if (!already_destroyed) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 101504a7887..f8987e2c49d 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -196,16 +196,18 @@ 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) +static struct wine_vk_surface *wine_vk_surface_grab( struct wine_vk_surface *surface ) { - InterlockedIncrement(&surface->ref); + 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) +static void wine_vk_surface_release( struct wine_vk_surface *surface ) { - if (InterlockedDecrement(&surface->ref)) - return; + int refcount = InterlockedDecrement( &surface->ref ); + TRACE( "surface %p, refcount %d.\n", surface, refcount ); + if (refcount) return;
if (surface->entry.next) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 18 ++++++++++++++++++ dlls/winex11.drv/window.c | 1 + dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 20 insertions(+)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 005a429f3df..635a90d9689 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -251,6 +251,20 @@ void destroy_vk_surface( HWND hwnd ) pthread_mutex_unlock( &vulkan_mutex ); }
+void resize_vk_surfaces( HWND hwnd, Window active, int mask, XWindowChanges *changes ) +{ + struct wine_vk_surface *surface; + + pthread_mutex_lock( &vulkan_mutex ); + LIST_FOR_EACH_ENTRY( surface, &surface_list, struct wine_vk_surface, entry ) + { + if (surface->hwnd != hwnd) continue; + if (!surface->window || surface->window == active) continue; + XConfigureWindow( gdi_display, surface->window, mask, changes ); + } + pthread_mutex_unlock( &vulkan_mutex ); +} + void vulkan_thread_detach(void) { struct wine_vk_surface *surface, *next; @@ -753,6 +767,10 @@ void destroy_vk_surface( HWND hwnd ) { }
+void resize_vk_surfaces( HWND hwnd, Window active, int mask, XWindowChanges changes ) +{ +} + void vulkan_thread_detach(void) { } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index f5c62c8e26f..e9106a81261 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1432,6 +1432,7 @@ static void sync_client_position( struct x11drv_win_data *data, TRACE( "setting client win %lx pos %d,%d,%dx%d changes=%x\n", data->client_window, changes.x, changes.y, changes.width, changes.height, mask ); XConfigureWindow( gdi_display, data->client_window, mask, &changes ); + resize_vk_surfaces( data->hwnd, data->client_window, mask, &changes ); } }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index caebb115e74..a6406099771 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -647,6 +647,7 @@ extern void sync_gl_drawable( HWND hwnd, BOOL known_child ) DECLSPEC_HIDDEN; extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN; extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN; extern void destroy_vk_surface( HWND hwnd ) DECLSPEC_HIDDEN; +extern void resize_vk_surfaces( HWND hwnd, Window active, int mask, XWindowChanges *changes ); extern void vulkan_thread_detach(void) DECLSPEC_HIDDEN;
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/vulkan.c | 2 ++ dlls/winevulkan/make_vulkan | 2 ++ dlls/winex11.drv/vulkan.c | 2 ++ include/wine/vulkan_driver.h | 6 ++++++ 4 files changed, 12 insertions(+)
diff --git a/dlls/winemac.drv/vulkan.c b/dlls/winemac.drv/vulkan.c index 00f5e8465ab..0c1a11af63d 100644 --- a/dlls/winemac.drv/vulkan.c +++ b/dlls/winemac.drv/vulkan.c @@ -591,6 +591,8 @@ static VkSurfaceKHR macdrv_wine_get_native_surface(VkSurfaceKHR surface)
static const struct vulkan_funcs vulkan_funcs = { + NULL, + NULL, macdrv_vkCreateInstance, macdrv_vkCreateSwapchainKHR, macdrv_vkCreateWin32SurfaceKHR, diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 9163f543c15..17a410f81bf 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -236,6 +236,8 @@ FUNCTION_OVERRIDES = { "vkGetPhysicalDeviceWin32PresentationSupportKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC},
# VK_KHR_swapchain + "vkAcquireNextImageKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC}, + "vkAcquireNextImage2KHR": {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC}, "vkCreateSwapchainKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC}, "vkDestroySwapchainKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC}, "vkGetSwapchainImagesKHR": {"dispatch" : True, "driver" : True, "thunk" : ThunkType.PUBLIC}, diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 635a90d9689..fd4c5168901 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -704,6 +704,8 @@ static VkSurfaceKHR X11DRV_wine_get_native_surface(VkSurfaceKHR surface)
static const struct vulkan_funcs vulkan_funcs = { + NULL, + NULL, X11DRV_vkCreateInstance, X11DRV_vkCreateSwapchainKHR, X11DRV_vkCreateWin32SurfaceKHR, diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index c9ac98b252b..61cdf7c69fe 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -21,6 +21,8 @@ struct vulkan_funcs * needs to provide. Other function calls will be provided indirectly by dispatch * tables part of dispatchable Vulkan objects such as VkInstance or vkDevice. */ + VkResult (*p_vkAcquireNextImage2KHR)(VkDevice, const VkAcquireNextImageInfoKHR *, uint32_t *); + VkResult (*p_vkAcquireNextImageKHR)(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t *); VkResult (*p_vkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); VkResult (*p_vkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKHR *, const VkAllocationCallbacks *, VkSwapchainKHR *); VkResult (*p_vkCreateWin32SurfaceKHR)(VkInstance, const VkWin32SurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); @@ -53,6 +55,10 @@ static inline void *get_vulkan_driver_device_proc_addr(
name += 2;
+ if (!strcmp(name, "AcquireNextImage2KHR")) + return vulkan_funcs->p_vkAcquireNextImage2KHR; + if (!strcmp(name, "AcquireNextImageKHR")) + return vulkan_funcs->p_vkAcquireNextImageKHR; if (!strcmp(name, "CreateSwapchainKHR")) return vulkan_funcs->p_vkCreateSwapchainKHR; if (!strcmp(name, "DestroySwapchainKHR"))
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/vulkan.c | 63 +++++++++++++++++++++++++++++++++++++-- dlls/winex11.drv/window.c | 19 ++++++++++++ dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index fd4c5168901..37cbcf08d3d 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,37 @@ 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 ))) + { + if (data->client_window != surface->window) + { + detach_client_window( data, data->client_window ); + 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 +761,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 e9106a81261..2f04dfb09c4 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1549,6 +1549,25 @@ Window get_dummy_parent(void) return dummy_parent; }
+/********************************************************************** + * attach_client_window + */ +void attach_client_window( struct x11drv_win_data *data, Window window ) +{ + if (!data->whole_window || data->client_window == window) return; + + 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;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/init.c | 8 ++++---- dlls/winex11.drv/opengl.c | 40 +++++++++++++++++++-------------------- dlls/winex11.drv/x11drv.h | 8 ++++---- 3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index c3d54da1d4d..35364884e50 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -243,16 +243,16 @@ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_d return TRUE; } break; - case X11DRV_FLUSH_GL_DRAWABLE: - if (in_count >= sizeof(struct x11drv_escape_flush_gl_drawable)) + case X11DRV_PRESENT_DRAWABLE: + if (in_count >= sizeof(struct x11drv_escape_present_drawable)) { - const struct x11drv_escape_flush_gl_drawable *data = in_data; + const struct x11drv_escape_present_drawable *data = in_data; RECT rect = physDev->dc_rect;
OffsetRect( &rect, -physDev->dc_rect.left, -physDev->dc_rect.top ); if (data->flush) XFlush( gdi_display ); XSetFunction( gdi_display, physDev->gc, GXcopy ); - XCopyArea( gdi_display, data->gl_drawable, physDev->drawable, physDev->gc, + XCopyArea( gdi_display, data->drawable, physDev->drawable, physDev->gc, 0, 0, rect.right, rect.bottom, physDev->dc_rect.left, physDev->dc_rect.top ); add_device_bounds( physDev, &rect ); diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index bb8f13f78b9..dd0753a624a 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1980,20 +1980,20 @@ static BOOL glxdrv_wglShareLists(struct wgl_context *org, struct wgl_context *de
static void wglFinish(void) { - struct x11drv_escape_flush_gl_drawable escape; + struct x11drv_escape_present_drawable escape; struct gl_drawable *gl; struct wgl_context *ctx = NtCurrentTeb()->glContext;
- escape.code = X11DRV_FLUSH_GL_DRAWABLE; - escape.gl_drawable = 0; + escape.code = X11DRV_PRESENT_DRAWABLE; + escape.drawable = 0; escape.flush = FALSE;
if ((gl = get_gl_drawable( NtUserWindowFromDC( ctx->hdc ), 0 ))) { switch (gl->type) { - case DC_GL_PIXMAP_WIN: escape.gl_drawable = gl->pixmap; break; - case DC_GL_CHILD_WIN: escape.gl_drawable = gl->window; break; + case DC_GL_PIXMAP_WIN: escape.drawable = gl->pixmap; break; + case DC_GL_CHILD_WIN: escape.drawable = gl->window; break; default: break; } sync_context(ctx); @@ -2001,26 +2001,26 @@ static void wglFinish(void) }
pglFinish(); - if (escape.gl_drawable) + if (escape.drawable) NtGdiExtEscape( ctx->hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); }
static void wglFlush(void) { - struct x11drv_escape_flush_gl_drawable escape; + struct x11drv_escape_present_drawable escape; struct gl_drawable *gl; struct wgl_context *ctx = NtCurrentTeb()->glContext;
- escape.code = X11DRV_FLUSH_GL_DRAWABLE; - escape.gl_drawable = 0; + escape.code = X11DRV_PRESENT_DRAWABLE; + escape.drawable = 0; escape.flush = FALSE;
if ((gl = get_gl_drawable( NtUserWindowFromDC( ctx->hdc ), 0 ))) { switch (gl->type) { - case DC_GL_PIXMAP_WIN: escape.gl_drawable = gl->pixmap; break; - case DC_GL_CHILD_WIN: escape.gl_drawable = gl->window; break; + case DC_GL_PIXMAP_WIN: escape.drawable = gl->pixmap; break; + case DC_GL_CHILD_WIN: escape.drawable = gl->window; break; default: break; } sync_context(ctx); @@ -2028,7 +2028,7 @@ static void wglFlush(void) }
pglFlush(); - if (escape.gl_drawable) + if (escape.drawable) NtGdiExtEscape( ctx->hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); }
@@ -3348,15 +3348,15 @@ static void X11DRV_WineGL_LoadExtensions(void) */ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) { - struct x11drv_escape_flush_gl_drawable escape; + struct x11drv_escape_present_drawable escape; struct gl_drawable *gl; struct wgl_context *ctx = NtCurrentTeb()->glContext; INT64 ust, msc, sbc, target_sbc = 0;
TRACE("(%p)\n", hdc);
- escape.code = X11DRV_FLUSH_GL_DRAWABLE; - escape.gl_drawable = 0; + escape.code = X11DRV_PRESENT_DRAWABLE; + escape.drawable = 0; escape.flush = !pglXWaitForSbcOML;
if (!(gl = get_gl_drawable( NtUserWindowFromDC( hdc ), hdc ))) @@ -3377,7 +3377,7 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) { case DC_GL_PIXMAP_WIN: if (ctx) sync_context( ctx ); - escape.gl_drawable = gl->pixmap; + escape.drawable = gl->pixmap; if (pglXCopySubBufferMESA) { /* (glX)SwapBuffers has an implicit glFlush effect, however * GLX_MESA_copy_sub_buffer doesn't. Make sure GL is flushed before @@ -3398,10 +3398,10 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) case DC_GL_WINDOW: case DC_GL_CHILD_WIN: if (ctx) sync_context( ctx ); - if (gl->type == DC_GL_CHILD_WIN) escape.gl_drawable = gl->window; + if (gl->type == DC_GL_CHILD_WIN) escape.drawable = gl->window; /* fall through */ default: - if (escape.gl_drawable && pglXSwapBuffersMscOML) + if (escape.drawable && pglXSwapBuffersMscOML) { pglFlush(); target_sbc = pglXSwapBuffersMscOML( gdi_display, gl->drawable, 0, 0, 0 ); @@ -3411,12 +3411,12 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) break; }
- if (escape.gl_drawable && pglXWaitForSbcOML) + if (escape.drawable && pglXWaitForSbcOML) pglXWaitForSbcOML( gdi_display, gl->drawable, target_sbc, &ust, &msc, &sbc );
release_gl_drawable( gl );
- if (escape.gl_drawable) + if (escape.drawable) NtGdiExtEscape( ctx->hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); return TRUE; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 82a1fb062ea..b7d09dad779 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -346,7 +346,7 @@ enum x11drv_escape_codes X11DRV_GET_DRAWABLE, /* get current drawable for a DC */ X11DRV_START_EXPOSURES, /* start graphics exposures */ X11DRV_END_EXPOSURES, /* end graphics exposures */ - X11DRV_FLUSH_GL_DRAWABLE /* flush changes made to the gl drawable */ + X11DRV_PRESENT_DRAWABLE, /* present the drawable on screen */ };
struct x11drv_escape_set_drawable @@ -365,10 +365,10 @@ struct x11drv_escape_get_drawable int pixel_format; /* internal GL pixel format */ };
-struct x11drv_escape_flush_gl_drawable +struct x11drv_escape_present_drawable { - enum x11drv_escape_codes code; /* escape code (X11DRV_FLUSH_GL_DRAWABLE) */ - Drawable gl_drawable; /* GL drawable */ + enum x11drv_escape_codes code; /* escape code (X11DRV_PRESENT_DRAWABLE) */ + Drawable drawable; /* GL / VK drawable */ BOOL flush; /* flush X11 before copying */ };