From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/init.c | 187 ++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/vulkan.c | 186 +------------------------------------ dlls/winex11.drv/x11drv.h | 1 + 3 files changed, 191 insertions(+), 183 deletions(-)
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 125b3583a1b..4806bd835a3 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -31,6 +31,7 @@ #include "winbase.h" #include "winreg.h" #include "x11drv.h" +#include "xcomposite.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv); @@ -255,6 +256,192 @@ HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ) return 0; }
+static const struct client_surface_funcs x11drv_client_surface_funcs; + +struct x11drv_client_surface +{ + struct client_surface client; + Window window; + RECT rect; + + HDC hdc_src; + HDC hdc_dst; +}; + +static struct x11drv_client_surface *impl_from_client_surface( struct client_surface *client ) +{ + return CONTAINING_RECORD( client, struct x11drv_client_surface, client ); +} + +static void x11drv_client_surface_destroy( struct client_surface *client ) +{ + struct x11drv_client_surface *surface = impl_from_client_surface( client ); + HWND hwnd = client->hwnd; + + TRACE( "%s\n", debugstr_client_surface( client ) ); + + if (surface->window) destroy_client_window( hwnd, surface->window ); + if (surface->hdc_dst) NtGdiDeleteObjectApp( surface->hdc_dst ); + if (surface->hdc_src) NtGdiDeleteObjectApp( surface->hdc_src ); +} + +static void x11drv_client_surface_detach( struct client_surface *client ) +{ + struct x11drv_client_surface *surface = impl_from_client_surface( client ); + Window client_window = surface->window; + struct x11drv_win_data *data; + HWND hwnd = client->hwnd; + + TRACE( "%s\n", debugstr_client_surface( client ) ); + + if ((data = get_win_data( hwnd ))) + { + detach_client_window( data, client_window ); + release_win_data( data ); + } +} + +static void client_surface_update_size( HWND hwnd, struct x11drv_client_surface *surface ) +{ + XWindowChanges changes; + RECT rect; + + NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) ); + if (EqualRect( &surface->rect, &rect )) return; + + changes.width = min( max( 1, rect.right ), 65535 ); + changes.height = min( max( 1, rect.bottom ), 65535 ); + XConfigureWindow( gdi_display, surface->window, CWWidth | CWHeight, &changes ); + surface->rect = rect; +} + +static void client_surface_update_offscreen( HWND hwnd, struct x11drv_client_surface *surface ) +{ + BOOL offscreen = needs_offscreen_rendering( hwnd ); + struct x11drv_win_data *data; + + if (InterlockedExchange(&surface->client.offscreen, offscreen) == offscreen) + { + if (!offscreen && (data = get_win_data( hwnd ))) + { + attach_client_window( data, surface->window ); + release_win_data( data ); + } + return; + } + + if (!offscreen) + { +#ifdef SONAME_LIBXCOMPOSITE + if (usexcomposite) pXCompositeUnredirectWindow( gdi_display, surface->window, CompositeRedirectManual ); +#endif + if (surface->hdc_dst) + { + NtGdiDeleteObjectApp( surface->hdc_dst ); + surface->hdc_dst = NULL; + } + if (surface->hdc_src) + { + NtGdiDeleteObjectApp( surface->hdc_src ); + surface->hdc_src = NULL; + } + } + else + { + static const WCHAR displayW[] = {'D','I','S','P','L','A','Y'}; + UNICODE_STRING device_str = RTL_CONSTANT_STRING(displayW); + surface->hdc_dst = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); + surface->hdc_src = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); + set_dc_drawable( surface->hdc_src, surface->window, &surface->rect, IncludeInferiors ); +#ifdef SONAME_LIBXCOMPOSITE + if (usexcomposite) pXCompositeRedirectWindow( gdi_display, surface->window, CompositeRedirectManual ); +#endif + } + + if ((data = get_win_data( hwnd ))) + { + if (offscreen) detach_client_window( data, surface->window ); + else attach_client_window( data, surface->window ); + release_win_data( data ); + } +} + +static void x11drv_client_surface_update( struct client_surface *client ) +{ + struct x11drv_client_surface *surface = impl_from_client_surface( client ); + HWND hwnd = client->hwnd; + + TRACE( "%s\n", debugstr_client_surface( client ) ); + + client_surface_update_size( hwnd, surface ); + client_surface_update_offscreen( hwnd, surface ); +} + +static void X11DRV_client_surface_present( struct client_surface *client, HDC hdc ) +{ + struct x11drv_client_surface *surface = impl_from_client_surface( client ); + HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + struct x11drv_win_data *data; + RECT rect_dst, rect; + Drawable window; + HRGN region; + + client_surface_update_size( hwnd, surface ); + client_surface_update_offscreen( hwnd, surface ); + + if (!hdc) return; + window = X11DRV_get_whole_window( toplevel ); + region = get_dc_monitor_region( hwnd, hdc ); + + NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + + if ((data = get_win_data( toplevel ))) + { + OffsetRect( &rect_dst, data->rects.client.left - data->rects.visible.left, + data->rects.client.top - data->rects.visible.top ); + release_win_data( data ); + } + + if (get_dc_drawable( surface->hdc_dst, &rect ) != window || !EqualRect( &rect, &rect_dst )) + set_dc_drawable( surface->hdc_dst, window, &rect_dst, IncludeInferiors ); + if (region) NtGdiExtSelectClipRgn( surface->hdc_dst, region, RGN_COPY ); + + NtGdiStretchBlt( surface->hdc_dst, 0, 0, rect_dst.right - rect_dst.left, rect_dst.bottom - rect_dst.top, + surface->hdc_src, 0, 0, surface->rect.right, surface->rect.bottom, SRCCOPY, 0 ); + + if (region) NtGdiDeleteObjectApp( region ); +} + +static const struct client_surface_funcs x11drv_client_surface_funcs = +{ + .destroy = x11drv_client_surface_destroy, + .detach = x11drv_client_surface_detach, + .update = x11drv_client_surface_update, + .present = X11DRV_client_surface_present, +}; + +Window x11drv_client_surface_create( HWND hwnd, struct client_surface **client ) +{ + struct x11drv_client_surface *surface; + + if (!(surface = client_surface_create( sizeof(*surface), &x11drv_client_surface_funcs, hwnd ))) + { + ERR("Failed to allocate vulkan surface for hwnd=%p\n", hwnd); + return None; + } + if (!(surface->window = create_client_window( hwnd, &default_visual, default_colormap ))) + { + ERR("Failed to allocate client window for hwnd=%p\n", hwnd); + client_surface_release( &surface->client ); + return None; + } + NtUserGetClientRect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) ); + + *client = &surface->client; + return surface->window; +} + /********************************************************************** * ExtEscape (X11DRV.@) */ diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index ee72e5ed69a..407df86169e 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -61,22 +61,6 @@ static VkResult (*pvkCreateXlibSurfaceKHR)(VkInstance, const VkXlibSurfaceCreate static VkBool32 (*pvkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice, uint32_t, Display *, VisualID);
static const struct vulkan_driver_funcs x11drv_vulkan_driver_funcs; -static const struct client_surface_funcs x11drv_vulkan_surface_funcs; - -struct x11drv_vulkan_surface -{ - struct client_surface client; - Window window; - RECT rect; - - HDC hdc_src; - HDC hdc_dst; -}; - -static struct x11drv_vulkan_surface *impl_from_client_surface( struct client_surface *client ) -{ - return CONTAINING_RECORD( client, struct x11drv_vulkan_surface, client ); -}
static VkResult X11DRV_vulkan_surface_create( HWND hwnd, const struct vulkan_instance *instance, VkSurfaceKHR *handle, struct client_surface **client ) @@ -86,177 +70,21 @@ static VkResult X11DRV_vulkan_surface_create( HWND hwnd, const struct vulkan_ins .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, .dpy = gdi_display, }; - struct x11drv_vulkan_surface *surface;
TRACE( "%p %p %p %p\n", hwnd, instance, handle, client );
- if (!(surface = client_surface_create( sizeof(*surface), &x11drv_vulkan_surface_funcs, hwnd ))) - { - ERR("Failed to allocate vulkan surface for hwnd=%p\n", hwnd); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - if (!(surface->window = create_client_window( hwnd, &default_visual, default_colormap ))) - { - ERR("Failed to allocate client window for hwnd=%p\n", hwnd); - client_surface_release( &surface->client ); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - NtUserGetClientRect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) ); - - info.window = surface->window; + if (!(info.window = x11drv_client_surface_create( hwnd, client ))) return VK_ERROR_OUT_OF_HOST_MEMORY; if (pvkCreateXlibSurfaceKHR( instance->host.instance, &info, NULL /* allocator */, handle )) { ERR("Failed to create Xlib surface\n"); - client_surface_release( &surface->client ); + client_surface_release( *client ); return VK_ERROR_OUT_OF_HOST_MEMORY; }
- *client = &surface->client; - - TRACE( "Created surface 0x%s, client %p\n", wine_dbgstr_longlong( *handle ), *client ); + TRACE( "Created surface 0x%s, client %s\n", wine_dbgstr_longlong( *handle ), debugstr_client_surface( *client ) ); return VK_SUCCESS; }
-static void x11drv_vulkan_surface_destroy( struct client_surface *client ) -{ - struct x11drv_vulkan_surface *surface = impl_from_client_surface( client ); - HWND hwnd = client->hwnd; - - TRACE( "%s\n", debugstr_client_surface( client ) ); - - if (surface->window) destroy_client_window( hwnd, surface->window ); - if (surface->hdc_dst) NtGdiDeleteObjectApp( surface->hdc_dst ); - if (surface->hdc_src) NtGdiDeleteObjectApp( surface->hdc_src ); -} - -static void x11drv_vulkan_surface_detach( struct client_surface *client ) -{ - struct x11drv_vulkan_surface *surface = impl_from_client_surface( client ); - Window client_window = surface->window; - struct x11drv_win_data *data; - HWND hwnd = client->hwnd; - - TRACE( "%s\n", debugstr_client_surface( client ) ); - - if ((data = get_win_data( hwnd ))) - { - detach_client_window( data, client_window ); - release_win_data( data ); - } -} - -static void vulkan_surface_update_size( HWND hwnd, struct x11drv_vulkan_surface *surface ) -{ - XWindowChanges changes; - RECT rect; - - NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) ); - if (EqualRect( &surface->rect, &rect )) return; - - changes.width = min( max( 1, rect.right ), 65535 ); - changes.height = min( max( 1, rect.bottom ), 65535 ); - XConfigureWindow( gdi_display, surface->window, CWWidth | CWHeight, &changes ); - surface->rect = rect; -} - -static void vulkan_surface_update_offscreen( HWND hwnd, struct x11drv_vulkan_surface *surface ) -{ - BOOL offscreen = needs_offscreen_rendering( hwnd ); - struct x11drv_win_data *data; - - if (InterlockedExchange(&surface->client.offscreen, offscreen) == offscreen) - { - if (!offscreen && (data = get_win_data( hwnd ))) - { - attach_client_window( data, surface->window ); - release_win_data( data ); - } - return; - } - - if (!offscreen) - { -#ifdef SONAME_LIBXCOMPOSITE - if (usexcomposite) pXCompositeUnredirectWindow( gdi_display, surface->window, CompositeRedirectManual ); -#endif - if (surface->hdc_dst) - { - NtGdiDeleteObjectApp( surface->hdc_dst ); - surface->hdc_dst = NULL; - } - if (surface->hdc_src) - { - NtGdiDeleteObjectApp( surface->hdc_src ); - surface->hdc_src = NULL; - } - } - else - { - static const WCHAR displayW[] = {'D','I','S','P','L','A','Y'}; - UNICODE_STRING device_str = RTL_CONSTANT_STRING(displayW); - surface->hdc_dst = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); - surface->hdc_src = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ); - set_dc_drawable( surface->hdc_src, surface->window, &surface->rect, IncludeInferiors ); -#ifdef SONAME_LIBXCOMPOSITE - if (usexcomposite) pXCompositeRedirectWindow( gdi_display, surface->window, CompositeRedirectManual ); -#endif - } - - if ((data = get_win_data( hwnd ))) - { - if (offscreen) detach_client_window( data, surface->window ); - else attach_client_window( data, surface->window ); - release_win_data( data ); - } -} - -static void x11drv_vulkan_surface_update( struct client_surface *client ) -{ - struct x11drv_vulkan_surface *surface = impl_from_client_surface( client ); - HWND hwnd = client->hwnd; - - TRACE( "%s\n", debugstr_client_surface( client ) ); - - vulkan_surface_update_size( hwnd, surface ); - vulkan_surface_update_offscreen( hwnd, surface ); -} - -static void X11DRV_vulkan_surface_present( struct client_surface *client, HDC hdc ) -{ - struct x11drv_vulkan_surface *surface = impl_from_client_surface( client ); - HWND hwnd = client->hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); - struct x11drv_win_data *data; - RECT rect_dst, rect; - Drawable window; - HRGN region; - - vulkan_surface_update_size( hwnd, surface ); - vulkan_surface_update_offscreen( hwnd, surface ); - - if (!hdc) return; - window = X11DRV_get_whole_window( toplevel ); - region = get_dc_monitor_region( hwnd, hdc ); - - NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); - NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); - - if ((data = get_win_data( toplevel ))) - { - OffsetRect( &rect_dst, data->rects.client.left - data->rects.visible.left, - data->rects.client.top - data->rects.visible.top ); - release_win_data( data ); - } - - if (get_dc_drawable( surface->hdc_dst, &rect ) != window || !EqualRect( &rect, &rect_dst )) - set_dc_drawable( surface->hdc_dst, window, &rect_dst, IncludeInferiors ); - if (region) NtGdiExtSelectClipRgn( surface->hdc_dst, region, RGN_COPY ); - - NtGdiStretchBlt( surface->hdc_dst, 0, 0, rect_dst.right - rect_dst.left, rect_dst.bottom - rect_dst.top, - surface->hdc_src, 0, 0, surface->rect.right, surface->rect.bottom, SRCCOPY, 0 ); - - if (region) NtGdiDeleteObjectApp( region ); -} - static VkBool32 X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, uint32_t index) { @@ -271,14 +99,6 @@ static const char *X11DRV_get_host_surface_extension(void) return "VK_KHR_xlib_surface"; }
-static const struct client_surface_funcs x11drv_vulkan_surface_funcs = -{ - .destroy = x11drv_vulkan_surface_destroy, - .detach = x11drv_vulkan_surface_detach, - .update = x11drv_vulkan_surface_update, - .present = X11DRV_vulkan_surface_present, -}; - static const struct vulkan_driver_funcs x11drv_vulkan_driver_funcs = { .p_vulkan_surface_create = X11DRV_vulkan_surface_create, diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index dfca33dcc97..1b24ad918f9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -359,6 +359,7 @@ extern BOOL needs_offscreen_rendering( HWND hwnd ); extern void set_dc_drawable( HDC hdc, Drawable drawable, const RECT *rect, int mode ); extern Drawable get_dc_drawable( HDC hdc, RECT *rect ); extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); +extern Window x11drv_client_surface_create( HWND hwnd, struct client_surface **client );
/************************************************************************** * X11 USER driver