From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/winemac.drv/cocoa_window.m | 68 +++++++++++++++++++++++++++++++++ dlls/winemac.drv/macdrv.h | 8 ++-- dlls/winemac.drv/macdrv_cocoa.h | 4 ++ dlls/winemac.drv/vulkan.c | 8 ++-- dlls/winemac.drv/window.c | 18 ++++++++- 5 files changed, 96 insertions(+), 10 deletions(-) diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 4c1ac93524f..2e62c471eba 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -3972,6 +3972,74 @@ void macdrv_view_release_metal_view(macdrv_metal_view v) }); } +@protocol WineMetalSwapChain <NSObject> + +- (CAMetalLayer*) layer; + +@end + +@interface MetalViewSwapChain : NSObject <WineMetalSwapChain> +{ + macdrv_metal_device device; + macdrv_metal_view metal_view; +} + +- (instancetype) initWithView:(macdrv_view)view; + +@end + +@implementation MetalViewSwapChain + +- (instancetype) initWithView:(macdrv_view)view +{ + self = [super init]; + if (!self) return nil; + + if (!(device = macdrv_create_metal_device())) + { + [self release]; + return nil; + } + if (!(metal_view = macdrv_view_create_metal_view(view, device))) + { + macdrv_release_metal_device(device); + device = NULL; + [self release]; + return nil; + } + return self; +} + +- (CAMetalLayer*) layer +{ + return (CAMetalLayer*)macdrv_view_get_metal_layer(metal_view); +} + +- (void) dealloc +{ + if (metal_view) macdrv_view_release_metal_view(metal_view); + if (device) macdrv_release_metal_device(device); + [super dealloc]; +} + +@end + +macdrv_metal_swapchain macdrv_create_view_swapchain(macdrv_view v) +{ + return (macdrv_metal_swapchain)[[MetalViewSwapChain alloc] initWithView:v]; +} + +macdrv_metal_layer macdrv_swapchain_get_layer(macdrv_metal_swapchain swapchain) +{ + return (macdrv_metal_layer)[(id<WineMetalSwapChain>)swapchain layer]; +} + + +void macdrv_destroy_swapchain(macdrv_metal_swapchain swapchain) +{ + [(id<WineMetalSwapChain>)swapchain release]; +} + bool macdrv_get_view_backing_size(macdrv_view v, int backing_size[2]) { WineContentView* view = (WineContentView*)v; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 6316a096365..4462ef99b73 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -193,10 +193,9 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p struct macdrv_client_surface { - struct client_surface client; - macdrv_view cocoa_view; - macdrv_metal_device metal_device; - macdrv_metal_view metal_view; + struct client_surface client; + macdrv_view cocoa_view; + macdrv_metal_swapchain metal_swapchain; }; static inline struct macdrv_client_surface *impl_from_client_surface(struct client_surface *client) @@ -205,6 +204,7 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p } extern struct macdrv_client_surface *macdrv_client_surface_create(HWND hwnd); +extern BOOL macdrv_client_surface_acquire_metal_swapchain(struct macdrv_client_surface *surface); extern struct macdrv_win_data *get_win_data(HWND hwnd); extern void release_win_data(struct macdrv_win_data *data); diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 381808479ce..fdc4222d296 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -106,6 +106,7 @@ typedef struct macdrv_opaque_metal_device* macdrv_metal_device; typedef struct macdrv_opaque_metal_view* macdrv_metal_view; typedef struct macdrv_opaque_metal_layer* macdrv_metal_layer; +typedef struct macdrv_opaque_metal_swapchain* macdrv_metal_swapchain; typedef struct macdrv_opaque_status_item* macdrv_status_item; struct macdrv_event; struct macdrv_query; @@ -527,6 +528,9 @@ extern void macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, extern macdrv_metal_view macdrv_view_create_metal_view(macdrv_view v, macdrv_metal_device d); extern macdrv_metal_layer macdrv_view_get_metal_layer(macdrv_metal_view v); extern void macdrv_view_release_metal_view(macdrv_metal_view v); +extern macdrv_metal_swapchain macdrv_create_view_swapchain(macdrv_view v); +extern macdrv_metal_layer macdrv_swapchain_get_layer(macdrv_metal_swapchain swapchain); +extern void macdrv_destroy_swapchain(macdrv_metal_swapchain swapchain); extern bool macdrv_get_view_backing_size(macdrv_view v, int backing_size[2]); extern void macdrv_set_view_backing_size(macdrv_view v, const int backing_size[2]); extern uint32_t macdrv_window_background_color(void); diff --git a/dlls/winemac.drv/vulkan.c b/dlls/winemac.drv/vulkan.c index 02c6a20a03c..f1643e3e5c4 100644 --- a/dlls/winemac.drv/vulkan.c +++ b/dlls/winemac.drv/vulkan.c @@ -49,8 +49,8 @@ static VkResult macdrv_vulkan_surface_create(HWND hwnd, const struct vulkan_inst TRACE("%p %p %p %p\n", hwnd, instance, handle, client); if (!(surface = macdrv_client_surface_create(hwnd))) return VK_ERROR_OUT_OF_HOST_MEMORY; - if (!(surface->metal_device = macdrv_create_metal_device())) goto err; - if (!(surface->metal_view = macdrv_view_create_metal_view(surface->cocoa_view, surface->metal_device))) goto err; + + if (!macdrv_client_surface_acquire_metal_swapchain(surface)) goto err; if (instance->p_vkCreateMetalSurfaceEXT) { @@ -58,7 +58,7 @@ static VkResult macdrv_vulkan_surface_create(HWND hwnd, const struct vulkan_inst create_info_host.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; create_info_host.pNext = NULL; create_info_host.flags = 0; /* reserved */ - create_info_host.pLayer = macdrv_view_get_metal_layer(surface->metal_view); + create_info_host.pLayer = macdrv_swapchain_get_layer(surface->metal_swapchain); res = instance->p_vkCreateMetalSurfaceEXT(instance->host.instance, &create_info_host, NULL /* allocator */, handle); } @@ -68,7 +68,7 @@ static VkResult macdrv_vulkan_surface_create(HWND hwnd, const struct vulkan_inst create_info_host.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; create_info_host.pNext = NULL; create_info_host.flags = 0; /* reserved */ - create_info_host.pView = macdrv_view_get_metal_layer(surface->metal_view); + create_info_host.pView = macdrv_swapchain_get_layer(surface->metal_swapchain); res = instance->p_vkCreateMacOSSurfaceMVK(instance->host.instance, &create_info_host, NULL /* allocator */, handle); } diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 2cc11b7dc1e..47c08e87e89 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1076,8 +1076,7 @@ static void macdrv_client_surface_destroy(struct client_surface *client) TRACE("%s\n", debugstr_client_surface(client)); - if (surface->metal_view) macdrv_view_release_metal_view(surface->metal_view); - if (surface->metal_device) macdrv_release_metal_device(surface->metal_device); + if (surface->metal_swapchain) macdrv_destroy_swapchain(surface->metal_swapchain); } static void macdrv_client_surface_detach(struct client_surface *client) @@ -1167,6 +1166,21 @@ struct macdrv_client_surface *macdrv_client_surface_create(HWND hwnd) return surface; } +BOOL macdrv_client_surface_acquire_metal_swapchain(struct macdrv_client_surface *surface) +{ + HWND hwnd = surface->client.hwnd; + struct macdrv_win_data *data; + + if (surface->metal_swapchain) return TRUE; + + if ((data = get_win_data(hwnd))) + { + release_win_data(data); + surface->metal_swapchain = macdrv_create_view_swapchain(surface->cocoa_view); + } + return surface->metal_swapchain != NULL; +} + /********************************************************************** * SetDesktopWindow (MACDRV.@) */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10935