From: Rémi Bernon <rbernon(a)codeweavers.com> The client rect might be empty or invalid. Fallout 3 in particular does a bogus call sequence after restoring minimized window which causes the window and client rects to be empty: SetRect(&rect, 0, 0, width, height); AdjustWindowRectEx(&rect, style, FALSE, 0); SetWindowPos(hwnd, 0, rect.left, rect.bottom, rect.right - rect.left, rect.top - rect.bottom, 0); We either need to hook the window messages and inhibit such window size changes, or we need to avoid relying on client and window rect when in fullscreen mode. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58443 --- dlls/wined3d/context_gl.c | 17 +++++++++++++---- dlls/wined3d/swapchain.c | 32 ++++++++++++++++++++++---------- dlls/wined3d/texture.c | 13 ++++++++++--- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index ac1b9370fc1..2b19664230e 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2391,11 +2391,20 @@ static void wined3d_context_gl_get_rt_size(const struct wined3d_context_gl *cont if (rt->swapchain) { - RECT window_size; + const struct wined3d_swapchain_desc *desc = &rt->swapchain->state.desc; - GetClientRect(context_gl->window, &window_size); - size->cx = window_size.right - window_size.left; - size->cy = window_size.bottom - window_size.top; + if (!desc->windowed) + { + size->cx = desc->backbuffer_width; + size->cy = desc->backbuffer_height; + } + else + { + RECT client_rect; + GetClientRect(context_gl->window, &client_rect); + size->cx = client_rect.right - client_rect.left; + size->cy = client_rect.bottom - client_rect.top; + } return; } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index f19f51d0e51..664a8001e50 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -206,6 +206,7 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, unsigned int swap_interval, uint32_t flags) { + const struct wined3d_swapchain_desc *desc = &swapchain->state.desc; RECT s, d; TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, swap_interval %u, flags %#x.\n", @@ -226,14 +227,16 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, if (!src_rect) { - SetRect(&s, 0, 0, swapchain->state.desc.backbuffer_width, - swapchain->state.desc.backbuffer_height); + SetRect(&s, 0, 0, desc->backbuffer_width, desc->backbuffer_height); src_rect = &s; } if (!dst_rect) { - GetClientRect(swapchain->win_handle, &d); + if (!desc->windowed) + SetRect(&d, 0, 0, desc->backbuffer_width, desc->backbuffer_height); + else + GetClientRect(swapchain->win_handle, &d); dst_rect = &d; } @@ -575,19 +578,28 @@ static void wined3d_swapchain_gl_rotate(struct wined3d_swapchain *swapchain, str static bool swapchain_present_is_partial_copy(struct wined3d_swapchain *swapchain, const RECT *dst_rect) { enum wined3d_swap_effect swap_effect = swapchain->state.desc.swap_effect; - RECT client_rect; - unsigned int t; + const struct wined3d_swapchain_desc *desc = &swapchain->state.desc; + unsigned int width, height; if (swap_effect != WINED3D_SWAP_EFFECT_COPY && swap_effect != WINED3D_SWAP_EFFECT_COPY_VSYNC) return false; - GetClientRect(swapchain->win_handle, &client_rect); + if (!desc->windowed) + { + width = desc->backbuffer_width; + height = desc->backbuffer_height; + } + else + { + RECT client_rect; + GetClientRect(swapchain->win_handle, &client_rect); + width = client_rect.right - client_rect.left; + height = client_rect.bottom - client_rect.top; + } - t = client_rect.right - client_rect.left; - if ((dst_rect->left && dst_rect->right) || abs(dst_rect->right - dst_rect->left) != t) + if ((dst_rect->left && dst_rect->right) || abs(dst_rect->right - dst_rect->left) != width) return true; - t = client_rect.bottom - client_rect.top; - if ((dst_rect->top && dst_rect->bottom) || abs(dst_rect->bottom - dst_rect->top) != t) + if ((dst_rect->top && dst_rect->bottom) || abs(dst_rect->bottom - dst_rect->top) != height) return true; return false; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index dd61a2f0d3c..784406cf245 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -68,12 +68,13 @@ static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const * origin, while D3D has a top-left origin. */ void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *texture, HWND window, RECT *rect) { + const struct wined3d_swapchain_desc *desc; unsigned int drawable_height; POINT offset = {0, 0}; - RECT windowsize; if (!texture->swapchain) return; + desc = &texture->swapchain->state.desc; if (texture == texture->swapchain->front_buffer) { @@ -81,8 +82,14 @@ void wined3d_texture_translate_drawable_coords(const struct wined3d_texture *tex OffsetRect(rect, offset.x, offset.y); } - GetClientRect(window, &windowsize); - drawable_height = windowsize.bottom - windowsize.top; + if (!desc->windowed) + drawable_height = desc->backbuffer_height; + else + { + RECT client_rect; + GetClientRect(window, &client_rect); + drawable_height = client_rect.bottom - client_rect.top; + } rect->top = drawable_height - rect->top; rect->bottom = drawable_height - rect->bottom; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9585