-- v2: win32u: Only inflate dirty rect when dpi conversion is performed in expose_window_surface(). win32u: Don't redraw window in expose_window_surface() if window has surface.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/win32u/window.c | 58 ++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 43 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 15145667ce1..afe68d08d53 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2202,36 +2202,11 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru return ret; }
-static HRGN expose_window_surface_rect( struct window_surface *surface, UINT flags, RECT dirty ) -{ - HRGN region, clipped; - - intersect_rect( &dirty, &dirty, &surface->rect ); - add_bounds_rect( &surface->bounds, &dirty ); - - if (!surface->clip_region || !flags) return 0; - - clipped = NtGdiCreateRectRgn( surface->rect.left, surface->rect.top, - surface->rect.right, surface->rect.bottom ); - NtGdiCombineRgn( clipped, clipped, surface->clip_region, RGN_DIFF ); - - region = NtGdiCreateRectRgn( dirty.left, dirty.top, dirty.right, dirty.bottom ); - if (NtGdiCombineRgn( region, region, clipped, RGN_DIFF ) <= NULLREGION) - { - NtGdiDeleteObjectApp( region ); - region = 0; - } - - NtGdiDeleteObjectApp( clipped ); - return region; -} - static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT dpi ) { struct window_surface *surface; struct window_rects rects; RECT window_rect; - HRGN region = 0; WND *win;
if (!(win = get_win_ptr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE; @@ -2245,27 +2220,24 @@ static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT InflateRect( &window_rect, 1, 1 ); /* compensate rounding errors */ }
- if (surface) + if (!surface || surface == &dummy_surface) { - window_surface_lock( surface ); - - if (!rect) add_bounds_rect( &surface->bounds, &surface->rect ); - else - { - RECT dirty = window_rect; - OffsetRect( &dirty, rects.client.left - rects.visible.left, rects.client.top - rects.visible.top ); - if (!(region = expose_window_surface_rect( surface, flags, dirty ))) flags = 0; - else NtGdiOffsetRgn( region, rects.client.left - rects.visible.left, rects.client.top - rects.visible.top ); - } - - window_surface_unlock( surface ); - if (surface->alpha_mask) window_surface_flush( surface ); - - window_surface_release( surface ); + NtUserRedrawWindow( hwnd, rect ? &window_rect : NULL, NULL, flags ); + if (surface) window_surface_release( surface ); + return TRUE; }
- if (flags) NtUserRedrawWindow( hwnd, rect ? &window_rect : NULL, region, flags ); - if (region) NtGdiDeleteObjectApp( region ); + window_surface_lock( surface ); + if (!rect) add_bounds_rect( &surface->bounds, &surface->rect ); + else + { + OffsetRect( &window_rect, rects.client.left - rects.visible.left, rects.client.top - rects.visible.top ); + intersect_rect( &window_rect, &window_rect, &surface->rect ); + add_bounds_rect( &surface->bounds, &window_rect ); + } + window_surface_unlock( surface ); + if (surface->alpha_mask) window_surface_flush( surface ); + window_surface_release( surface ); return TRUE; }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/win32u/window.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index afe68d08d53..7b761257306 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2207,6 +2207,7 @@ static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT struct window_surface *surface; struct window_rects rects; RECT window_rect; + UINT win_dpi; WND *win;
if (!(win = get_win_ptr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE; @@ -2216,8 +2217,12 @@ static BOOL expose_window_surface( HWND hwnd, UINT flags, const RECT *rect, UINT
if (rect) { - window_rect = map_dpi_rect( *rect, dpi, get_dpi_for_window( hwnd ) ); - InflateRect( &window_rect, 1, 1 ); /* compensate rounding errors */ + if ((win_dpi = get_dpi_for_window( hwnd )) != dpi) + { + window_rect = map_dpi_rect( *rect, dpi, win_dpi ); + InflateRect( &window_rect, 1, 1 ); /* compensate rounding errors */ + } + else window_rect = *rect; }
if (!surface || surface == &dummy_surface)
v2: - just don't ever redraw window in expose_window_surface() if it has a surface.
Rémi Bernon (@rbernon) commented about dlls/win32u/window.c:
if (rect) {
window_rect = map_dpi_rect( *rect, dpi, get_dpi_for_window( hwnd ) );
if ((win_dpi = get_dpi_for_window( hwnd )) != dpi)
{
window_rect = map_dpi_rect( *rect, dpi, win_dpi ); InflateRect( &window_rect, 1, 1 ); /* compensate rounding errors */ }
else window_rect = *rect;
The inflation was mostly only necessary because of the DPI scaled window surface which was partially redrawn and which sometimes showed artifact on the boundaries of the exposed region because of rounding errors. If we're not triggering redraw when there's a surface, I think this also becomes mostly unnecessary.
We don't have DPI scaling without window surface upstream anyway, and I'm not sure it's worth spending time upstreaming DPI scaled server-side DC rendering when we would need some more generic implementation ultimately anyway (ie: always use surfaces, and proper compositing).