From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index a2699d66e51..c96ed7bde18 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -38,7 +38,7 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur uint32_t serial) { struct wayland_surface *surface; - BOOL initial_configure = FALSE; + BOOL should_post = FALSE, initial_configure = FALSE; HWND hwnd = data;
TRACE("serial=%u\n", serial); @@ -52,16 +52,17 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur /* If we have a previously requested config, we have already sent a * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case, * avoid sending another message to reduce message queue traffic. */ - BOOL should_post = surface->requested.serial == 0; + should_post = surface->requested.serial == 0; initial_configure = surface->current.serial == 0; surface->pending.serial = serial; surface->requested = surface->pending; memset(&surface->pending, 0, sizeof(surface->pending)); - if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0); }
pthread_mutex_unlock(&surface->mutex);
+ if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0); + /* Flush the window surface in case there is content that we weren't * able to flush before due to the lack of the initial configure. */ if (initial_configure)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 22 +--------------------- dlls/winewayland.drv/vulkan.c | 18 +----------------- dlls/winewayland.drv/waylanddrv.h | 2 ++ dlls/winewayland.drv/window.c | 21 +++++++++++++++++++++ 4 files changed, 25 insertions(+), 38 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index fd13bdbb406..b99d80cbcf2 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -308,26 +308,6 @@ static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl) } }
-static void wayland_gl_drawable_sync_surface_state(struct wayland_gl_drawable *gl) -{ - struct wayland_surface *wayland_surface; - - if (!(wayland_surface = wayland_surface_lock_hwnd(gl->hwnd))) return; - - wayland_surface_ensure_contents(wayland_surface); - - /* Handle any processed configure request, to ensure the related - * surface state is applied by the compositor. */ - if (wayland_surface->processing.serial && - wayland_surface->processing.processed && - wayland_surface_reconfigure(wayland_surface)) - { - wl_surface_commit(wayland_surface->wl_surface); - } - - pthread_mutex_unlock(&wayland_surface->mutex); -} - static BOOL wgl_context_make_current(struct wgl_context *ctx, HDC draw_hdc, HDC read_hdc) { BOOL ret; @@ -753,7 +733,7 @@ static BOOL wayland_wglSwapBuffers(HDC hdc) if (!(gl = wayland_gl_drawable_get(NtUserWindowFromDC(hdc), hdc))) return FALSE;
if (ctx) wgl_context_refresh(ctx); - wayland_gl_drawable_sync_surface_state(gl); + ensure_window_surface_contents(gl->hwnd); /* Although all the EGL surfaces we create are double-buffered, we want to * use some as single-buffered, so avoid swapping those. */ if (gl->double_buffered) p_eglSwapBuffers(egl_display, gl->surface); diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 16084175013..a828d736da1 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -138,23 +138,7 @@ static void wayland_vulkan_surface_detach(HWND hwnd, void *private)
static void wayland_vulkan_surface_presented(HWND hwnd, VkResult result) { - struct wayland_surface *wayland_surface; - - if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) - { - wayland_surface_ensure_contents(wayland_surface); - - /* Handle any processed configure request, to ensure the related - * surface state is applied by the compositor. */ - if (wayland_surface->processing.serial && - wayland_surface->processing.processed && - wayland_surface_reconfigure(wayland_surface)) - { - wl_surface_commit(wayland_surface->wl_surface); - } - - pthread_mutex_unlock(&wayland_surface->mutex); - } + ensure_window_surface_contents(hwnd); }
static VkBool32 wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 40f86526cd2..46c283865d8 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -297,6 +297,8 @@ struct wayland_win_data struct wayland_win_data *wayland_win_data_get(HWND hwnd); void wayland_win_data_release(struct wayland_win_data *data);
+void ensure_window_surface_contents(HWND hwnd); + /********************************************************************** * Wayland Keyboard */ diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 73a8de37f77..9665d33375e 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -710,3 +710,24 @@ struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd)
return surface; } + +void ensure_window_surface_contents(HWND hwnd) +{ + struct wayland_surface *wayland_surface; + + if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + { + wayland_surface_ensure_contents(wayland_surface); + + /* Handle any processed configure request, to ensure the related + * surface state is applied by the compositor. */ + if (wayland_surface->processing.serial && + wayland_surface->processing.processed && + wayland_surface_reconfigure(wayland_surface)) + { + wl_surface_commit(wayland_surface->wl_surface); + } + + pthread_mutex_unlock(&wayland_surface->mutex); + } +}
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 23 +++++++++++++++++++++++ dlls/winewayland.drv/window_surface.c | 14 +------------- 3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 46c283865d8..496a6f1ea60 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -297,6 +297,7 @@ struct wayland_win_data struct wayland_win_data *wayland_win_data_get(HWND hwnd); void wayland_win_data_release(struct wayland_win_data *data);
+BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region); void ensure_window_surface_contents(HWND hwnd);
/********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 9665d33375e..096dd2bb5fb 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -711,6 +711,29 @@ struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) return surface; }
+BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region) +{ + struct wayland_surface *wayland_surface; + BOOL committed = FALSE; + + if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + { + if (wayland_surface_reconfigure(wayland_surface)) + { + wayland_surface_attach_shm(wayland_surface, shm_buffer, damage_region); + wl_surface_commit(wayland_surface->wl_surface); + committed = TRUE; + } + else + { + TRACE("Wayland surface not configured yet, not flushing\n"); + } + pthread_mutex_unlock(&wayland_surface->mutex); + } + + return committed; +} + void ensure_window_surface_contents(HWND hwnd) { struct wayland_surface *wayland_surface; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 570c186861b..0d5eb0bd9ff 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -386,19 +386,7 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface,
wayland_shm_buffer_copy_data(shm_buffer, color_bits, &surface_rect, copy_from_window_region);
- pthread_mutex_lock(&wws->wayland_surface->mutex); - if (wayland_surface_reconfigure(wws->wayland_surface)) - { - wayland_surface_attach_shm(wws->wayland_surface, shm_buffer, - surface_damage_region); - wl_surface_commit(wws->wayland_surface->wl_surface); - flushed = TRUE; - } - else - { - TRACE("Wayland surface not configured yet, not flushing\n"); - } - pthread_mutex_unlock(&wws->wayland_surface->mutex); + flushed = set_window_surface_contents(window_surface->hwnd, shm_buffer, surface_damage_region); wl_display_flush(process_wayland.wl_display);
NtGdiSetRectRgn(shm_buffer->damage_region, 0, 0, 0, 0);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 20 ++++++++++++++++++++ dlls/winewayland.drv/window_surface.c | 17 ++++++----------- 3 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 496a6f1ea60..8d554d6a3fa 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -298,6 +298,7 @@ struct wayland_win_data *wayland_win_data_get(HWND hwnd); void wayland_win_data_release(struct wayland_win_data *data);
BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region); +struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd); void ensure_window_surface_contents(HWND hwnd);
/********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 096dd2bb5fb..45ef876c4eb 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -728,12 +728,32 @@ BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffe { TRACE("Wayland surface not configured yet, not flushing\n"); } + + /* Update the latest window buffer for the wayland surface. Note that we + * only care whether the buffer contains the latest window contents, + * it's irrelevant if it was actually committed or not. */ + if (wayland_surface->latest_window_buffer) + wayland_shm_buffer_unref(wayland_surface->latest_window_buffer); + wayland_shm_buffer_ref((wayland_surface->latest_window_buffer = shm_buffer)); + pthread_mutex_unlock(&wayland_surface->mutex); }
return committed; }
+struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd) +{ + struct wayland_surface *wayland_surface; + struct wayland_shm_buffer *shm_buffer; + + if (!(wayland_surface = wayland_surface_lock_hwnd(hwnd))) return NULL; + if ((shm_buffer = wayland_surface->latest_window_buffer)) wayland_shm_buffer_ref(shm_buffer); + pthread_mutex_unlock(&wayland_surface->mutex); + + return shm_buffer; +} + void ensure_window_surface_contents(HWND hwnd) { struct wayland_surface *wayland_surface; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 0d5eb0bd9ff..0e4747fce2f 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -324,7 +324,7 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, { RECT surface_rect = {.right = color_info->bmiHeader.biWidth, .bottom = abs(color_info->bmiHeader.biHeight)}; struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface); - struct wayland_shm_buffer *shm_buffer = NULL; + struct wayland_shm_buffer *shm_buffer = NULL, *latest_buffer; BOOL flushed = FALSE; HRGN surface_damage_region = NULL; HRGN copy_from_window_region; @@ -353,12 +353,12 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, goto done; }
- if (wws->wayland_surface->latest_window_buffer) + if ((latest_buffer = get_window_surface_contents(window_surface->hwnd))) { - TRACE("latest_window_buffer=%p\n", wws->wayland_surface->latest_window_buffer); + TRACE("latest_window_buffer=%p\n", latest_buffer); /* If we have a latest buffer, use it as the source of all pixel * data that are not contained in the bounds of the flush... */ - if (wws->wayland_surface->latest_window_buffer != shm_buffer) + if (latest_buffer != shm_buffer) { HRGN copy_from_latest_region = NtGdiCreateRectRgn(0, 0, 0, 0); if (!copy_from_latest_region) @@ -368,13 +368,14 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, } NtGdiCombineRgn(copy_from_latest_region, shm_buffer->damage_region, surface_damage_region, RGN_DIFF); - wayland_shm_buffer_copy(wws->wayland_surface->latest_window_buffer, + wayland_shm_buffer_copy(latest_buffer, shm_buffer, copy_from_latest_region); NtGdiDeleteObjectApp(copy_from_latest_region); } /* ... and use the window_surface as the source of pixel data contained * in the flush bounds. */ copy_from_window_region = surface_damage_region; + wayland_shm_buffer_unref(latest_buffer); } else { @@ -390,12 +391,6 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, wl_display_flush(process_wayland.wl_display);
NtGdiSetRectRgn(shm_buffer->damage_region, 0, 0, 0, 0); - /* Update the latest window buffer for the wayland surface. Note that we - * only care whether the buffer contains the latest window contents, - * it's irrelevant if it was actually committed or not. */ - if (wws->wayland_surface->latest_window_buffer) - wayland_shm_buffer_unref(wws->wayland_surface->latest_window_buffer); - wayland_shm_buffer_ref((wws->wayland_surface->latest_window_buffer = shm_buffer));
done: if (surface_damage_region) NtGdiDeleteObjectApp(surface_damage_region);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/window_surface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 0e4747fce2f..4e5ea3d366d 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -386,12 +386,11 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, }
wayland_shm_buffer_copy_data(shm_buffer, color_bits, &surface_rect, copy_from_window_region); + NtGdiSetRectRgn(shm_buffer->damage_region, 0, 0, 0, 0);
flushed = set_window_surface_contents(window_surface->hwnd, shm_buffer, surface_damage_region); wl_display_flush(process_wayland.wl_display);
- NtGdiSetRectRgn(shm_buffer->damage_region, 0, 0, 0, 0); - done: if (surface_damage_region) NtGdiDeleteObjectApp(surface_damage_region); return flushed;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/wayland_surface.c | 3 --- dlls/winewayland.drv/waylanddrv.h | 3 ++- dlls/winewayland.drv/window.c | 32 ++++++++++++++++---------- 3 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index c96ed7bde18..8acd43e1729 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -230,9 +230,6 @@ void wayland_surface_destroy(struct wayland_surface *surface)
pthread_mutex_unlock(&surface->mutex);
- if (surface->latest_window_buffer) - wayland_shm_buffer_unref(surface->latest_window_buffer); - wl_display_flush(process_wayland.wl_display);
pthread_mutex_destroy(&surface->mutex); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 8d554d6a3fa..fc2a0918b3d 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -198,7 +198,6 @@ struct wayland_surface struct wp_viewport *wp_viewport; pthread_mutex_t mutex; struct wayland_surface_config pending, requested, processing, current; - struct wayland_shm_buffer *latest_window_buffer; BOOL resizing; struct wayland_window_config window; struct wayland_client_surface *client; @@ -285,6 +284,8 @@ struct wayland_win_data struct rb_entry entry; /* hwnd that this private data belongs to */ HWND hwnd; + /* last buffer that was set as window contents */ + struct wayland_shm_buffer *window_contents; /* wayland surface (if any) for this window */ struct wayland_surface *wayland_surface; /* wine window_surface backing this window */ diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 45ef876c4eb..816ab843b91 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -125,6 +125,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data) window_surface_release(data->window_surface); } if (data->wayland_surface) wayland_surface_destroy(data->wayland_surface); + if (data->window_contents) wayland_shm_buffer_unref(data->window_contents); free(data); }
@@ -714,10 +715,15 @@ struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region) { struct wayland_surface *wayland_surface; + struct wayland_win_data *data; BOOL committed = FALSE;
- if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + if (!(data = wayland_win_data_get(hwnd))) return FALSE; + + if ((wayland_surface = data->wayland_surface)) { + pthread_mutex_lock(&wayland_surface->mutex); + if (wayland_surface_reconfigure(wayland_surface)) { wayland_surface_attach_shm(wayland_surface, shm_buffer, damage_region); @@ -729,27 +735,29 @@ BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffe TRACE("Wayland surface not configured yet, not flushing\n"); }
- /* Update the latest window buffer for the wayland surface. Note that we - * only care whether the buffer contains the latest window contents, - * it's irrelevant if it was actually committed or not. */ - if (wayland_surface->latest_window_buffer) - wayland_shm_buffer_unref(wayland_surface->latest_window_buffer); - wayland_shm_buffer_ref((wayland_surface->latest_window_buffer = shm_buffer)); - pthread_mutex_unlock(&wayland_surface->mutex); }
+ /* Update the latest window buffer for the wayland surface. Note that we + * only care whether the buffer contains the latest window contents, + * it's irrelevant if it was actually committed or not. */ + if (data->window_contents) + wayland_shm_buffer_unref(data->window_contents); + wayland_shm_buffer_ref((data->window_contents = shm_buffer)); + + wayland_win_data_release(data); + return committed; }
struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd) { - struct wayland_surface *wayland_surface; struct wayland_shm_buffer *shm_buffer; + struct wayland_win_data *data;
- if (!(wayland_surface = wayland_surface_lock_hwnd(hwnd))) return NULL; - if ((shm_buffer = wayland_surface->latest_window_buffer)) wayland_shm_buffer_ref(shm_buffer); - pthread_mutex_unlock(&wayland_surface->mutex); + if (!(data = wayland_win_data_get(hwnd))) return NULL; + if ((shm_buffer = data->window_contents)) wayland_shm_buffer_ref(shm_buffer); + wayland_win_data_release(data);
return shm_buffer; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/waylanddrv.h | 3 +-- dlls/winewayland.drv/window.c | 13 ++---------- dlls/winewayland.drv/window_surface.c | 30 ++++++++------------------- 3 files changed, 12 insertions(+), 34 deletions(-)
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index fc2a0918b3d..636424230be 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -271,8 +271,7 @@ void wayland_shm_buffer_unref(struct wayland_shm_buffer *shm_buffer); * Wayland window surface */
-void wayland_window_surface_update_wayland_surface(struct window_surface *surface, const RECT *visible_rect, - struct wayland_surface *wayland_surface); +void wayland_window_surface_set_visible_rect(struct window_surface *surface, const RECT *visible_rect);
/********************************************************************** * Wayland Window diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 816ab843b91..e0f3f235cac 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -119,11 +119,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
pthread_mutex_unlock(&win_data_mutex);
- if (data->window_surface) - { - wayland_window_surface_update_wayland_surface(data->window_surface, NULL, NULL); - window_surface_release(data->window_surface); - } + if (data->window_surface) window_surface_release(data->window_surface); if (data->wayland_surface) wayland_surface_destroy(data->wayland_surface); if (data->window_contents) wayland_shm_buffer_unref(data->window_contents); free(data); @@ -210,8 +206,6 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat /* We don't want wayland surfaces for child windows. */ if (parent != NtUserGetDesktopWindow() && parent != 0) { - if (data->window_surface) - wayland_window_surface_update_wayland_surface(data->window_surface, NULL, NULL); if (surface) wayland_surface_destroy(surface); surface = NULL; goto out; @@ -248,10 +242,6 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
pthread_mutex_unlock(&surface->mutex);
- if (data->window_surface) - wayland_window_surface_update_wayland_surface(data->window_surface, - &data->rects.visible, surface); - /* Size/position changes affect the effective pointer constraint, so update * it as needed. */ if (data->hwnd == NtUserGetForegroundWindow()) reapply_cursor_clipping(); @@ -466,6 +456,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, cons data->window_surface = surface;
wayland_win_data_update_wayland_surface(data); + if (surface) wayland_window_surface_set_visible_rect(surface, &data->rects.visible); if (data->wayland_surface) wayland_win_data_update_wayland_state(data);
wayland_win_data_release(data); diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 4e5ea3d366d..5131d6043cf 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -43,7 +43,6 @@ struct wayland_buffer_queue struct wayland_window_surface { struct window_surface header; - struct wayland_surface *wayland_surface; struct wayland_buffer_queue *wayland_buffer_queue; };
@@ -329,10 +328,9 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, HRGN surface_damage_region = NULL; HRGN copy_from_window_region;
- if (!wws->wayland_surface || !wws->wayland_buffer_queue) + if (!wws->wayland_buffer_queue) { - ERR("missing wayland surface=%p or buffer_queue=%p, returning\n", - wws->wayland_surface, wws->wayland_buffer_queue); + ERR("missing buffer_queue=%p, returning\n", wws->wayland_buffer_queue); goto done; }
@@ -444,9 +442,9 @@ static struct window_surface *wayland_window_surface_create(HWND hwnd, const REC /*********************************************************************** * wayland_window_surface_update_wayland_surface */ -void wayland_window_surface_update_wayland_surface(struct window_surface *window_surface, const RECT *visible_rect, - struct wayland_surface *wayland_surface) +void wayland_window_surface_set_visible_rect(struct window_surface *window_surface, const RECT *visible_rect) { + UINT width = visible_rect->right - visible_rect->left, height = visible_rect->bottom - visible_rect->top; struct wayland_window_surface *wws;
/* ignore calls with the dummy surface */ @@ -455,23 +453,13 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *window wws = wayland_window_surface_cast(window_surface); window_surface_lock(window_surface);
- TRACE("surface=%p hwnd=%p visible_rect=%s wayland_surface=%p\n", wws, window_surface->hwnd, - wine_dbgstr_rect(visible_rect), wayland_surface); + TRACE("surface=%p hwnd=%p visible_rect=%s\n", wws, window_surface->hwnd, wine_dbgstr_rect(visible_rect));
- wws->wayland_surface = wayland_surface; - - if (wws->wayland_buffer_queue) - { - wayland_buffer_queue_destroy(wws->wayland_buffer_queue); - wws->wayland_buffer_queue = NULL; - } - - /* We only need a buffer queue if we have a surface to commit to. */ - if (wws->wayland_surface) + if (!wws->wayland_buffer_queue || wws->wayland_buffer_queue->width != width || + wws->wayland_buffer_queue->height != height) { - wws->wayland_buffer_queue = - wayland_buffer_queue_create(visible_rect->right - visible_rect->left, - visible_rect->bottom - visible_rect->top); + if (wws->wayland_buffer_queue) wayland_buffer_queue_destroy(wws->wayland_buffer_queue); + wws->wayland_buffer_queue = wayland_buffer_queue_create(width, height); }
window_surface_unlock(window_surface);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 7 +-- dlls/winewayland.drv/wayland_surface.c | 82 +++++++++++++++----------- dlls/winewayland.drv/waylanddrv.h | 1 + 3 files changed, 49 insertions(+), 41 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index b99d80cbcf2..fe7499f5256 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -218,13 +218,10 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for client_width = client_height = 1; pthread_mutex_unlock(&wayland_surface->mutex); } - else if ((wayland_surface = wayland_surface_create(0))) + else { - gl->client = wayland_surface_get_client(wayland_surface); + gl->client = wayland_client_surface_create(hwnd); client_width = client_height = 1; - /* It's fine to destroy the wayland surface, the client surface - * can safely outlive it. */ - wayland_surface_destroy(wayland_surface); } if (!gl->client) goto err;
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 8acd43e1729..545378368c5 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -768,36 +768,26 @@ BOOL wayland_client_surface_release(struct wayland_client_surface *client) return TRUE; }
-/********************************************************************** - * wayland_surface_get_client - */ -struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) +struct wayland_client_surface *wayland_client_surface_create(HWND hwnd) { + struct wayland_client_surface *client; struct wl_region *empty_region;
- if (surface->client) - { - InterlockedIncrement(&surface->client->ref); - return surface->client; - } - - surface->client = calloc(1, sizeof(*surface->client)); - if (!surface->client) + if (!(client = calloc(1, sizeof(*client)))) { ERR("Failed to allocate space for client surface\n"); - goto err; + return NULL; } + client->ref = 1;
- surface->client->ref = 1; - - surface->client->wl_surface = + client->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor); - if (!surface->client->wl_surface) + if (!client->wl_surface) { ERR("Failed to create client wl_surface\n"); goto err; } - wl_surface_set_user_data(surface->client->wl_surface, surface->hwnd); + wl_surface_set_user_data(client->wl_surface, hwnd);
/* Let parent handle all pointer events. */ empty_region = wl_compositor_create_region(process_wayland.wl_compositor); @@ -806,40 +796,60 @@ struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface ERR("Failed to create wl_region\n"); goto err; } - wl_surface_set_input_region(surface->client->wl_surface, empty_region); + wl_surface_set_input_region(client->wl_surface, empty_region); wl_region_destroy(empty_region);
- surface->client->wl_subsurface = + if (process_wayland.wp_viewporter) + { + client->wp_viewport = + wp_viewporter_get_viewport(process_wayland.wp_viewporter, + client->wl_surface); + } + + return client; + +err: + wayland_client_surface_release(client); + return NULL; +} + +/********************************************************************** + * wayland_surface_get_client + */ +struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface) +{ + struct wayland_client_surface *client; + + if ((client = surface->client)) + { + InterlockedIncrement(&client->ref); + return client; + } + + if (!(client = wayland_client_surface_create(surface->hwnd))) + return NULL; + + client->wl_subsurface = wl_subcompositor_get_subsurface(process_wayland.wl_subcompositor, - surface->client->wl_surface, + client->wl_surface, surface->wl_surface); - if (!surface->client->wl_subsurface) + if (!client->wl_subsurface) { ERR("Failed to create client wl_subsurface\n"); goto err; } /* Present contents independently of the parent surface. */ - wl_subsurface_set_desync(surface->client->wl_subsurface); - - if (process_wayland.wp_viewporter) - { - surface->client->wp_viewport = - wp_viewporter_get_viewport(process_wayland.wp_viewporter, - surface->client->wl_surface); - } + wl_subsurface_set_desync(client->wl_subsurface);
wayland_surface_reconfigure_client(surface); /* Commit to apply subsurface positioning. */ wl_surface_commit(surface->wl_surface);
- return surface->client; + surface->client = client; + return client;
err: - if (surface->client) - { - wayland_client_surface_release(surface->client); - surface->client = NULL; - } + wayland_client_surface_release(client); return NULL; }
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 636424230be..6d3a4b78474 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -253,6 +253,7 @@ 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); +struct wayland_client_surface *wayland_client_surface_create(HWND hwnd); struct wayland_client_surface *wayland_surface_get_client(struct wayland_surface *surface); BOOL wayland_client_surface_release(struct wayland_client_surface *client); void wayland_surface_ensure_contents(struct wayland_surface *surface);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 53 +++++++++++-------- dlls/winewayland.drv/vulkan.c | 28 +++++----- dlls/winewayland.drv/wayland_keyboard.c | 10 ++-- dlls/winewayland.drv/wayland_pointer.c | 40 +++++++++++---- dlls/winewayland.drv/wayland_surface.c | 30 +++++------ dlls/winewayland.drv/waylanddrv.h | 2 - dlls/winewayland.drv/window.c | 68 ++++++++++--------------- 7 files changed, 120 insertions(+), 111 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index fe7499f5256..94ff32c81f1 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -166,12 +166,12 @@ static void wayland_gl_drawable_release(struct wayland_gl_drawable *gl) if (gl->client) { HWND hwnd = wl_surface_get_user_data(gl->client->wl_surface); - struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd); + struct wayland_win_data *data = wayland_win_data_get(hwnd);
- if (wayland_client_surface_release(gl->client) && wayland_surface) - wayland_surface->client = NULL; + if (wayland_client_surface_release(gl->client) && data && data->wayland_surface) + data->wayland_surface->client = NULL;
- if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex); + if (data) wayland_win_data_release(data); }
free(gl); @@ -194,6 +194,7 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for struct wayland_gl_drawable *gl; struct wayland_surface *wayland_surface; int client_width = 0, client_height = 0; + struct wayland_win_data *data;
TRACE("hwnd=%p format=%d\n", hwnd, format);
@@ -207,16 +208,24 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for /* Get the client surface for the HWND. If don't have a wayland surface * (e.g., HWND_MESSAGE windows) just create a dummy surface to act as the * target render surface. */ - if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + if ((data = wayland_win_data_get(hwnd))) { - gl->client = wayland_surface_get_client(wayland_surface); - client_width = wayland_surface->window.client_rect.right - - wayland_surface->window.client_rect.left; - client_height = wayland_surface->window.client_rect.bottom - - wayland_surface->window.client_rect.top; - if (client_width == 0 || client_height == 0) + if (!(wayland_surface = data->wayland_surface)) + { + gl->client = wayland_client_surface_create(hwnd); client_width = client_height = 1; - pthread_mutex_unlock(&wayland_surface->mutex); + } + else + { + gl->client = wayland_surface_get_client(wayland_surface); + client_width = wayland_surface->window.client_rect.right - + wayland_surface->window.client_rect.left; + client_height = wayland_surface->window.client_rect.bottom - + wayland_surface->window.client_rect.top; + if (client_width == 0 || client_height == 0) + client_width = client_height = 1; + } + wayland_win_data_release(data); } else { @@ -285,23 +294,27 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne
static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl) { - int client_width, client_height; + int client_width = 0, client_height = 0; struct wayland_surface *wayland_surface; + struct wayland_win_data *data;
if (InterlockedCompareExchange(&gl->resized, FALSE, TRUE)) { - if (!(wayland_surface = wayland_surface_lock_hwnd(gl->hwnd))) return; + if (!(data = wayland_win_data_get(gl->hwnd))) return; + + if ((wayland_surface = data->wayland_surface)) + { + client_width = wayland_surface->window.client_rect.right - + wayland_surface->window.client_rect.left; + client_height = wayland_surface->window.client_rect.bottom - + wayland_surface->window.client_rect.top; + }
- client_width = wayland_surface->window.client_rect.right - - wayland_surface->window.client_rect.left; - client_height = wayland_surface->window.client_rect.bottom - - wayland_surface->window.client_rect.top; if (client_width == 0 || client_height == 0) client_width = client_height = 1; + wayland_win_data_release(data);
wl_egl_window_resize(gl->wl_egl_window, client_width, client_height, 0, 0); - - pthread_mutex_unlock(&wayland_surface->mutex); } }
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index a828d736da1..7a075a925b7 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -58,22 +58,15 @@ static VkBool32 (*pvkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalD
static const struct vulkan_driver_funcs wayland_vulkan_driver_funcs;
-static HWND wine_vk_surface_get_hwnd(struct wayland_client_surface *client) -{ - return wl_surface_get_user_data(client->wl_surface); -} - static void wine_vk_surface_destroy(struct wayland_client_surface *client) { - HWND hwnd = wine_vk_surface_get_hwnd(client); - struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd); + HWND hwnd = wl_surface_get_user_data(client->wl_surface); + struct wayland_win_data *data = wayland_win_data_get(hwnd);
- if (wayland_client_surface_release(client) && wayland_surface) - { - wayland_surface->client = NULL; - } + if (wayland_client_surface_release(client) && data && data->wayland_surface) + data->wayland_surface->client = NULL;
- if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex); + if (data) wayland_win_data_release(data); }
static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, VkSurfaceKHR *surface, void **private) @@ -82,18 +75,21 @@ static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, Vk VkWaylandSurfaceCreateInfoKHR create_info_host; struct wayland_surface *wayland_surface; struct wayland_client_surface *client; + struct wayland_win_data *data;
TRACE("%p %p %p %p\n", hwnd, instance, surface, private);
- wayland_surface = wayland_surface_lock_hwnd(hwnd); - if (!wayland_surface) + if (!(data = wayland_win_data_get(hwnd))) { ERR("Failed to find wayland surface for hwnd=%p\n", hwnd); return VK_ERROR_OUT_OF_HOST_MEMORY; }
- client = wayland_surface_get_client(wayland_surface); - pthread_mutex_unlock(&wayland_surface->mutex); + if ((wayland_surface = data->wayland_surface)) + client = wayland_surface_get_client(wayland_surface); + else + client = wayland_client_surface_create(hwnd); + wayland_win_data_release(data);
if (!client) { diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index 5c2fe15273e..8f7b6dce30f 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -736,12 +736,13 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, xkb_keymap_unref(xkb_keymap); }
-static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, +static void keyboard_handle_enter(void *private, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *wl_surface, struct wl_array *keys) { struct wayland_keyboard *keyboard = &process_wayland.keyboard; struct wayland_surface *surface; + struct wayland_win_data *data; HWND hwnd;
if (!wl_surface) return; @@ -758,7 +759,9 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/, (LPARAM)keyboard_hkl);
- if ((surface = wayland_surface_lock_hwnd(hwnd))) + if (!(data = wayland_win_data_get(hwnd))) return; + + if ((surface = data->wayland_surface)) { /* TODO: Drop the internal message and call NtUserSetForegroundWindow * directly once it's updated to not explicitly deactivate the old @@ -766,8 +769,9 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, * are in the same non-current thread. */ if (surface->window.managed) NtUserPostMessage(hwnd, WM_WAYLAND_SET_FOREGROUND, 0, 0); - pthread_mutex_unlock(&surface->mutex); } + + wayland_win_data_release(data); }
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 1d8acaeabd2..c1a364925f0 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -53,9 +53,15 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) HWND hwnd; POINT screen; struct wayland_surface *surface; + struct wayland_win_data *data;
if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; - if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + if (!(data = wayland_win_data_get(hwnd))) return; + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + }
window_rect = &surface->window.rect;
@@ -72,7 +78,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) if (screen.y >= window_rect->bottom) screen.y = window_rect->bottom - 1; else if (screen.y < window_rect->top) screen.y = window_rect->top;
- pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data);
/* Hardware input events are in physical coordinates. */ if (!NtUserLogicalToPerMonitorDPIPhysicalPoint(hwnd, &screen)) return; @@ -248,7 +254,7 @@ static const struct wl_pointer_listener pointer_listener = pointer_handle_axis_discrete };
-static void relative_pointer_v1_relative_motion(void *data, +static void relative_pointer_v1_relative_motion(void *private, struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, uint32_t utime_hi, uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, @@ -258,10 +264,16 @@ static void relative_pointer_v1_relative_motion(void *data, HWND hwnd; POINT screen, origin; struct wayland_surface *surface; + struct wayland_win_data *data; RECT window_rect;
if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; - if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + if (!(data = wayland_win_data_get(hwnd))) return; + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + }
window_rect = surface->window.rect;
@@ -270,7 +282,7 @@ static void relative_pointer_v1_relative_motion(void *data, wl_fixed_to_double(dy), (int *)&screen.x, (int *)&screen.y);
- pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data);
/* We clip the relative motion within the window rectangle so that * the NtUserLogicalToPerMonitorDPIPhysicalPoint calls later succeed. @@ -671,16 +683,22 @@ static void wayland_set_cursor(HWND hwnd, HCURSOR hcursor, BOOL use_hcursor) { struct wayland_pointer *pointer = &process_wayland.pointer; struct wayland_surface *surface; + struct wayland_win_data *data; double scale; BOOL reapply_clip = FALSE;
- if ((surface = wayland_surface_lock_hwnd(hwnd))) + if ((data = wayland_win_data_get(hwnd))) { + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + } scale = surface->window.scale; if (use_hcursor) surface->hcursor = hcursor; else hcursor = surface->hcursor; use_hcursor = TRUE; - pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data); } else { @@ -901,22 +919,24 @@ BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset) struct wayland_pointer *pointer = &process_wayland.pointer; struct wl_surface *wl_surface = NULL; struct wayland_surface *surface = NULL; + struct wayland_win_data *data; BOOL covers_vscreen = FALSE; RECT confine_rect;
TRACE("clip=%s reset=%d\n", wine_dbgstr_rect(clip), reset);
- if ((surface = wayland_surface_lock_hwnd(NtUserGetForegroundWindow()))) + if (!(data = wayland_win_data_get(NtUserGetForegroundWindow()))) return FALSE; + if ((surface = data->wayland_surface)) { wl_surface = surface->wl_surface; if (clip) wayland_surface_calc_confine(surface, clip, &confine_rect); covers_vscreen = wayland_surface_client_covers_vscreen(surface); - pthread_mutex_unlock(&surface->mutex); } + wayland_win_data_release(data);
/* Since we are running in the context of the foreground thread we know * that the wl_surface of the foreground HWND will not be invalidated, - * so we can access it without having the surface lock. */ + * so we can access it without having the win data lock. */ pthread_mutex_lock(&pointer->mutex); wayland_pointer_update_constraint(wl_surface, (clip && wl_surface) ? &confine_rect : NULL, diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 545378368c5..6e767b5d680 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -34,20 +34,21 @@
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
-static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface, +static void xdg_surface_handle_configure(void *private, struct xdg_surface *xdg_surface, uint32_t serial) { struct wayland_surface *surface; BOOL should_post = FALSE, initial_configure = FALSE; - HWND hwnd = data; + struct wayland_win_data *data; + HWND hwnd = private;
TRACE("serial=%u\n", serial);
- if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + if (!(data = wayland_win_data_get(hwnd))) return;
/* Handle this event only if wayland_surface is still associated with * the target xdg_surface. */ - if (surface->xdg_surface == xdg_surface) + if ((surface = data->wayland_surface) && surface->xdg_surface == xdg_surface) { /* If we have a previously requested config, we have already sent a * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case, @@ -59,7 +60,7 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur memset(&surface->pending, 0, sizeof(surface->pending)); }
- pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data);
if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0);
@@ -76,15 +77,16 @@ static const struct xdg_surface_listener xdg_surface_listener = xdg_surface_handle_configure };
-static void xdg_toplevel_handle_configure(void *data, +static void xdg_toplevel_handle_configure(void *private, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { struct wayland_surface *surface; - HWND hwnd = data; + HWND hwnd = private; uint32_t *state; enum wayland_surface_config_state config_state = 0; + struct wayland_win_data *data;
wl_array_for_each(state, states) { @@ -112,16 +114,16 @@ static void xdg_toplevel_handle_configure(void *data,
TRACE("hwnd=%p %dx%d,%#x\n", hwnd, width, height, config_state);
- if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + if (!(data = wayland_win_data_get(hwnd))) return;
- if (surface->xdg_toplevel == xdg_toplevel) + if ((surface = data->wayland_surface) && surface->xdg_toplevel == xdg_toplevel) { surface->pending.width = width; surface->pending.height = height; surface->pending.state = config_state; }
- pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data); }
static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) @@ -153,8 +155,6 @@ struct wayland_surface *wayland_surface_create(HWND hwnd)
TRACE("surface=%p\n", surface);
- pthread_mutex_init(&surface->mutex, NULL); - surface->hwnd = hwnd; surface->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor); if (!surface->wl_surface) @@ -202,8 +202,6 @@ void wayland_surface_destroy(struct wayland_surface *surface) process_wayland.keyboard.focused_hwnd = NULL; pthread_mutex_unlock(&process_wayland.keyboard.mutex);
- pthread_mutex_lock(&surface->mutex); - if (surface->wp_viewport) { wp_viewport_destroy(surface->wp_viewport); @@ -228,12 +226,8 @@ void wayland_surface_destroy(struct wayland_surface *surface) surface->wl_surface = NULL; }
- pthread_mutex_unlock(&surface->mutex); - wl_display_flush(process_wayland.wl_display);
- pthread_mutex_destroy(&surface->mutex); - free(surface); }
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 6d3a4b78474..32c356da625 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -196,7 +196,6 @@ struct wayland_surface struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct wp_viewport *wp_viewport; - pthread_mutex_t mutex; struct wayland_surface_config pending, requested, processing, current; BOOL resizing; struct wayland_window_config window; @@ -242,7 +241,6 @@ void wayland_surface_clear_role(struct wayland_surface *surface); void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region); -struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd); BOOL wayland_surface_reconfigure(struct wayland_surface *surface); BOOL wayland_surface_config_is_compatible(struct wayland_surface_config *conf, int width, int height, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index e0f3f235cac..82523581563 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -217,8 +217,6 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; xdg_visible = surface->xdg_toplevel != NULL;
- pthread_mutex_lock(&surface->mutex); - if (visible != xdg_visible) { /* If we have a pre-existing surface ensure it has no role. */ @@ -240,8 +238,6 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
wayland_win_data_get_config(data, &surface->window);
- pthread_mutex_unlock(&surface->mutex); - /* Size/position changes affect the effective pointer constraint, so update * it as needed. */ if (data->hwnd == NtUserGetForegroundWindow()) reapply_cursor_clipping(); @@ -256,8 +252,6 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) struct wayland_surface *surface = data->wayland_surface; BOOL processing_config;
- pthread_mutex_lock(&surface->mutex); - if (!surface->xdg_toplevel) goto out;
processing_config = surface->processing.serial && @@ -302,7 +296,6 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) }
out: - pthread_mutex_unlock(&surface->mutex); wl_display_flush(process_wayland.wl_display); }
@@ -472,20 +465,26 @@ static void wayland_configure_window(HWND hwnd) DWORD style; BOOL needs_enter_size_move = FALSE; BOOL needs_exit_size_move = FALSE; + struct wayland_win_data *data;
- if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + if (!(data = wayland_win_data_get(hwnd))) return; + if (!(surface = data->wayland_surface)) + { + wayland_win_data_release(data); + return; + }
if (!surface->xdg_toplevel) { TRACE("missing xdg_toplevel, returning\n"); - pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data); return; }
if (!surface->requested.serial) { TRACE("requested configure event already handled, returning\n"); - pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data); return; }
@@ -547,7 +546,7 @@ static void wayland_configure_window(HWND hwnd) wayland_surface_coords_to_window(surface, width, height, &window_width, &window_height);
- pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data);
TRACE("processing=%dx%d,%#x\n", width, height, state);
@@ -626,14 +625,16 @@ static enum xdg_toplevel_resize_edge hittest_to_resize_edge(WPARAM hittest) */ void WAYLAND_SetWindowText(HWND hwnd, LPCWSTR text) { - struct wayland_surface *surface = wayland_surface_lock_hwnd(hwnd); + struct wayland_surface *surface; + struct wayland_win_data *data;
TRACE("hwnd=%p text=%s\n", hwnd, wine_dbgstr_w(text));
- if (surface) + if ((data = wayland_win_data_get(hwnd))) { - if (surface->xdg_toplevel) wayland_surface_set_title(surface, text); - pthread_mutex_unlock(&surface->mutex); + if ((surface = data->wayland_surface) && surface->xdg_toplevel) + wayland_surface_set_title(surface, text); + wayland_win_data_release(data); } }
@@ -647,6 +648,7 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) uint32_t button_serial; struct wl_seat *wl_seat; struct wayland_surface *surface; + struct wayland_win_data *data;
TRACE("cmd=%lx hwnd=%p, %lx, %lx\n", (long)command, hwnd, (long)wparam, lparam); @@ -660,11 +662,11 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam)
if (command == SC_MOVE || command == SC_SIZE) { - if ((surface = wayland_surface_lock_hwnd(hwnd))) + if ((data = wayland_win_data_get(hwnd))) { pthread_mutex_lock(&process_wayland.seat.mutex); wl_seat = process_wayland.seat.wl_seat; - if (wl_seat && surface->xdg_toplevel && button_serial) + if (wl_seat && (surface = data->wayland_surface) && surface->xdg_toplevel && button_serial) { if (command == SC_MOVE) { @@ -677,7 +679,7 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) } } pthread_mutex_unlock(&process_wayland.seat.mutex); - pthread_mutex_unlock(&surface->mutex); + wayland_win_data_release(data); ret = 0; } } @@ -686,23 +688,6 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) return ret; }
-/********************************************************************** - * wayland_surface_lock_hwnd - */ -struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) -{ - struct wayland_win_data *data = wayland_win_data_get(hwnd); - struct wayland_surface *surface; - - if (!data) return NULL; - - if ((surface = data->wayland_surface)) pthread_mutex_lock(&surface->mutex); - - wayland_win_data_release(data); - - return surface; -} - BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffer, HRGN damage_region) { struct wayland_surface *wayland_surface; @@ -713,8 +698,6 @@ BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffe
if ((wayland_surface = data->wayland_surface)) { - pthread_mutex_lock(&wayland_surface->mutex); - if (wayland_surface_reconfigure(wayland_surface)) { wayland_surface_attach_shm(wayland_surface, shm_buffer, damage_region); @@ -725,8 +708,6 @@ BOOL set_window_surface_contents(HWND hwnd, struct wayland_shm_buffer *shm_buffe { TRACE("Wayland surface not configured yet, not flushing\n"); } - - pthread_mutex_unlock(&wayland_surface->mutex); }
/* Update the latest window buffer for the wayland surface. Note that we @@ -756,8 +737,11 @@ struct wayland_shm_buffer *get_window_surface_contents(HWND hwnd) void ensure_window_surface_contents(HWND hwnd) { struct wayland_surface *wayland_surface; + struct wayland_win_data *data; + + if (!(data = wayland_win_data_get(hwnd))) return;
- if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + if ((wayland_surface = data->wayland_surface)) { wayland_surface_ensure_contents(wayland_surface);
@@ -769,7 +753,7 @@ void ensure_window_surface_contents(HWND hwnd) { wl_surface_commit(wayland_surface->wl_surface); } - - pthread_mutex_unlock(&wayland_surface->mutex); } + + wayland_win_data_release(data); }
Thanks, this approach is serializing access across all Wayland surfaces, but I don't think that's a big loss and the simplicity it brings seems to be worth it.
This broader locking scheme has introduced a new deadlock situation, though, between `window_surface->mutex` and `win_data_mutex`:
Thread 1: **window_surface_lock** -> window_surface_flush -> {get,set}_window_surface_contents -> **wayland_win_data_get**
Thread 2: WAYLAND_WindowPosChanged -> **wayland_win_data_get** -> wayland_window_surface_set_visible_rect -> **window_surface_lock**
An example where I am seeing this consistently is while resizing firefox. Moving the call to `wayland_window_surface_set_visible_rect` after `wayland_win_data_release` in `WAYLAND_WindowPosChanged` seems to be a reasonable fix?
On Wed Aug 28 08:37:08 2024 +0000, Alexandros Frantzis wrote:
Thanks, this approach is serializing access across all Wayland surfaces, but I don't think that's a big loss and the simplicity it brings seems to be worth it. This broader locking scheme has introduced a new deadlock situation, though, between `window_surface->mutex` and `win_data_mutex`: Thread 1: **window_surface_lock** -> window_surface_flush -> {get,set}_window_surface_contents -> **wayland_win_data_get** Thread 2: WAYLAND_WindowPosChanged -> **wayland_win_data_get** -> wayland_window_surface_set_visible_rect -> **window_surface_lock** An example where I am seeing this consistently is while resizing firefox. Moving the call to `wayland_window_surface_set_visible_rect` after `wayland_win_data_release` in `WAYLAND_WindowPosChanged` seems to be a reasonable fix?
Sounds reasonable, then I'm tempted to get rid of this window surface buffer queue recreation entirely, removing the need for `wayland_window_surface_set_visible_rect` altogether. The only reason we do it I believe, is because buffers need to match the surface dimensions at the moment, but what about using `wp_viewport_set_source` to crop the buffers instead?
This would let us use the surface dimensions for the buffers, and only reallocate the queue and buffers when surface needs to be re-created, which seems to be its intended usage (we round the surface rectangles to multiple of 128 for that purpose).
It seems that the only thing preventing that is that wp_viewporter is currently optional, do you think it would be an issue to make it a requirement? I think it will let us make the code much simpler, and even allow further integration into win32u, allowing win32u to draw directly to the buffer for instance.
On Wed Aug 28 08:38:01 2024 +0000, Rémi Bernon wrote:
Sounds reasonable, then I'm tempted to get rid of this window surface buffer queue recreation entirely, removing the need for `wayland_window_surface_set_visible_rect` altogether. The only reason we do it I believe, is because buffers need to match the surface dimensions at the moment, but what about using `wp_viewport_set_source` to crop the buffers instead? This would let us use the surface dimensions for the buffers, and only reallocate the queue and buffers when surface needs to be re-created, which seems to be its intended usage (we round the surface rectangles to multiple of 128 for that purpose). It seems that the only thing preventing that is that wp_viewporter is currently optional, do you think it would be an issue to make it a requirement? I think it will let us make the code much simpler, and even allow further integration into win32u, allowing win32u to draw directly to the buffer for instance.
Something like https://gitlab.winehq.org/wine/wine/-/merge_requests/6386.