Commit 9439b3c3 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Use a client area subsurface as the Vulkan target.

Since we can't render to parts of surfaces, use a dedicated client area subsurface as the target of Vulkan rendering.
parent 51dbd708
......@@ -64,7 +64,7 @@ static const struct vulkan_funcs vulkan_funcs;
struct wine_vk_surface
{
struct wl_surface *client;
struct wayland_client_surface *client;
VkSurfaceKHR native;
};
......@@ -75,7 +75,20 @@ static struct wine_vk_surface *wine_vk_surface_from_handle(VkSurfaceKHR handle)
static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface)
{
if (wine_vk_surface->client) wl_surface_destroy(wine_vk_surface->client);
if (wine_vk_surface->client)
{
HWND hwnd = wl_surface_get_user_data(wine_vk_surface->client->wl_surface);
struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd);
if (wayland_client_surface_release(wine_vk_surface->client) &&
wayland_surface)
{
wayland_surface->client = NULL;
}
if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex);
}
free(wine_vk_surface);
}
......@@ -166,6 +179,7 @@ static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance,
VkResult res;
VkWaylandSurfaceCreateInfoKHR create_info_host;
struct wine_vk_surface *wine_vk_surface;
struct wayland_surface *wayland_surface;
TRACE("%p %p %p %p\n", instance, create_info, allocator, vk_surface);
......@@ -180,7 +194,18 @@ static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance,
goto err;
}
wine_vk_surface->client = wl_compositor_create_surface(process_wayland.wl_compositor);
wayland_surface = wayland_surface_lock_hwnd(create_info->hwnd);
if (!wayland_surface)
{
ERR("Failed to find wayland surface for hwnd=%p\n", create_info->hwnd);
/* VK_KHR_win32_surface only allows out of host and device memory as errors. */
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto err;
}
wine_vk_surface->client = wayland_surface_get_client(wayland_surface);
pthread_mutex_unlock(&wayland_surface->mutex);
if (!wine_vk_surface->client)
{
ERR("Failed to create client surface for hwnd=%p\n", create_info->hwnd);
......@@ -193,7 +218,7 @@ static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance,
create_info_host.pNext = NULL;
create_info_host.flags = 0; /* reserved */
create_info_host.display = process_wayland.wl_display;
create_info_host.surface = wine_vk_surface->client;
create_info_host.surface = wine_vk_surface->client->wl_surface;
res = pvkCreateWaylandSurfaceKHR(instance, &create_info_host,
NULL /* allocator */,
......
......@@ -149,6 +149,11 @@ static void registry_handle_global(void *data, struct wl_registry *registry,
process_wayland.wp_viewporter =
wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
}
else if (strcmp(interface, "wl_subcompositor") == 0)
{
process_wayland.wl_subcompositor =
wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
}
}
static void registry_handle_global_remove(void *data, struct wl_registry *registry,
......@@ -249,6 +254,11 @@ BOOL wayland_process_init(void)
ERR("Wayland compositor doesn't support wl_shm\n");
return FALSE;
}
if (!process_wayland.wl_subcompositor)
{
ERR("Wayland compositor doesn't support wl_subcompositor\n");
return FALSE;
}
wayland_init_display_devices(FALSE);
......
......@@ -687,3 +687,70 @@ void wayland_surface_coords_to_window(struct wayland_surface *surface,
*window_x = round(surface_x * surface->window.scale);
*window_y = round(surface_y * surface->window.scale);
}
/**********************************************************************
* wayland_client_surface_release
*/
BOOL wayland_client_surface_release(struct wayland_client_surface *client)
{
if (InterlockedDecrement(&client->ref)) return FALSE;
if (client->wl_subsurface)
wl_subsurface_destroy(client->wl_subsurface);
if (client->wl_surface)
wl_surface_destroy(client->wl_surface);
free(client);
return TRUE;
}
/**********************************************************************
* wayland_surface_get_client
*/
struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface)
{
if (surface->client)
{
InterlockedIncrement(&surface->client->ref);
return surface->client;
}
surface->client = calloc(1, sizeof(*surface->client));
if (!surface->client)
{
ERR("Failed to allocate space for client surface\n");
goto err;
}
surface->client->ref = 1;
surface->client->wl_surface =
wl_compositor_create_surface(process_wayland.wl_compositor);
if (!surface->client->wl_surface)
{
ERR("Failed to create client wl_surface\n");
goto err;
}
wl_surface_set_user_data(surface->client->wl_surface, surface->hwnd);
surface->client->wl_subsurface =
wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor,
surface->client->wl_surface,
surface->wl_surface);
if (!surface->client->wl_subsurface)
{
ERR("Failed to create client wl_subsurface\n");
goto err;
}
return surface->client;
err:
if (surface->client)
{
wayland_client_surface_release(surface->client);
surface->client = NULL;
}
return NULL;
}
......@@ -111,6 +111,7 @@ struct wayland
struct xdg_wm_base *xdg_wm_base;
struct wl_shm *wl_shm;
struct wp_viewporter *wp_viewporter;
struct wl_subcompositor *wl_subcompositor;
struct wayland_seat seat;
struct wayland_keyboard keyboard;
struct wayland_pointer pointer;
......@@ -163,6 +164,13 @@ struct wayland_window_config
double scale;
};
struct wayland_client_surface
{
LONG ref;
struct wl_surface *wl_surface;
struct wl_subsurface *wl_subsurface;
};
struct wayland_surface
{
HWND hwnd;
......@@ -175,6 +183,7 @@ struct wayland_surface
struct wayland_shm_buffer *latest_window_buffer;
BOOL resizing;
struct wayland_window_config window;
struct wayland_client_surface *client;
};
struct wayland_shm_buffer
......@@ -226,6 +235,8 @@ void wayland_surface_coords_from_window(struct wayland_surface *surface,
void wayland_surface_coords_to_window(struct wayland_surface *surface,
double surface_x, double surface_y,
int *window_x, int *window_y) DECLSPEC_HIDDEN;
struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) DECLSPEC_HIDDEN;
BOOL wayland_client_surface_release(struct wayland_client_surface *client) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland SHM buffer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment