win32u: Use a dedicated helper to move bits from a previous surface.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56766
This commit is contained in:
Rémi Bernon 2024-06-04 09:14:04 +02:00 committed by Alexandre Julliard
parent 09b9c1b5fe
commit feff510717
3 changed files with 55 additions and 55 deletions

View file

@ -1194,62 +1194,72 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn,
*
* Copy bits from a window surface; helper for move_window_bits and move_window_bits_parent.
*/
static void copy_bits_from_surface( HWND hwnd, struct window_surface *surface,
const RECT *dst, const RECT *src, BOOL same )
static void copy_bits_from_surface( HWND hwnd, const RECT *dst, const RECT *src )
{
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
void *bits;
UINT flags = UPDATE_NOCHILDREN | UPDATE_CLIPCHILDREN;
HRGN rgn = get_update_region( hwnd, &flags, NULL );
HDC hdc = NtUserGetDCEx( hwnd, rgn, DCX_CACHE | DCX_WINDOW | DCX_EXCLUDERGN );
if (same)
{
RECT rect = *src;
NtGdiStretchBlt( hdc, dst->left, dst->top, dst->right - dst->left, dst->bottom - dst->top,
hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SRCCOPY, 0 );
}
else
{
bits = surface->funcs->get_info( surface, info );
window_surface_lock( surface );
NtGdiSetDIBitsToDeviceInternal( hdc, dst->left, dst->top, dst->right - dst->left, dst->bottom - dst->top,
src->left - surface->rect.left, surface->rect.bottom - src->bottom,
0, surface->rect.bottom - surface->rect.top,
bits, info, DIB_RGB_COLORS, 0, 0, FALSE, NULL );
window_surface_unlock( surface );
}
NtGdiStretchBlt( hdc, dst->left, dst->top, dst->right - dst->left, dst->bottom - dst->top,
hdc, src->left, src->top, src->right - src->left, src->bottom - src->top, SRCCOPY, 0 );
NtUserReleaseDC( hwnd, hdc );
}
/***********************************************************************
* move_window_bits
*
* Move the window bits when a window is resized or its surface recreated.
* Move the window bits when a window is resized.
*/
void move_window_bits( HWND hwnd, struct window_surface *old_surface,
struct window_surface *new_surface,
const RECT *visible_rect, const RECT *old_visible_rect,
void move_window_bits( HWND hwnd, const RECT *visible_rect, const RECT *old_visible_rect,
const RECT *window_rect, const RECT *valid_rects )
{
RECT dst = valid_rects[0];
RECT src = valid_rects[1];
if (new_surface != old_surface ||
src.left - old_visible_rect->left != dst.left - visible_rect->left ||
if (src.left - old_visible_rect->left != dst.left - visible_rect->left ||
src.top - old_visible_rect->top != dst.top - visible_rect->top)
{
TRACE( "copying %s -> %s\n", wine_dbgstr_rect( &src ), wine_dbgstr_rect( &dst ));
if (new_surface != old_surface) OffsetRect( &src, -old_visible_rect->left, -old_visible_rect->top );
else OffsetRect( &src, -window_rect->left, -window_rect->top );
OffsetRect( &src, -window_rect->left, -window_rect->top );
OffsetRect( &dst, -window_rect->left, -window_rect->top );
copy_bits_from_surface( hwnd, old_surface, &dst, &src, new_surface == old_surface );
copy_bits_from_surface( hwnd, &dst, &src );
}
}
/***********************************************************************
* move_window_bits_surface
*
* Move the window bits from a previous window surface when its surface is recreated.
*/
void move_window_bits_surface( HWND hwnd, const RECT *window_rect, struct window_surface *old_surface,
const RECT *old_visible_rect, const RECT *valid_rects )
{
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
UINT flags = UPDATE_NOCHILDREN | UPDATE_CLIPCHILDREN;
HRGN rgn = get_update_region( hwnd, &flags, NULL );
HDC hdc = NtUserGetDCEx( hwnd, rgn, DCX_CACHE | DCX_WINDOW | DCX_EXCLUDERGN );
void *bits;
RECT dst = valid_rects[0];
RECT src = valid_rects[1];
TRACE( "copying %s -> %s\n", wine_dbgstr_rect( &src ), wine_dbgstr_rect( &dst ));
OffsetRect( &src, -old_visible_rect->left, -old_visible_rect->top );
OffsetRect( &dst, -window_rect->left, -window_rect->top );
bits = old_surface->funcs->get_info( old_surface, info );
window_surface_lock( old_surface );
NtGdiSetDIBitsToDeviceInternal( hdc, dst.left, dst.top, dst.right - dst.left, dst.bottom - dst.top,
src.left - old_surface->rect.left, old_surface->rect.bottom - src.bottom,
0, old_surface->rect.bottom - old_surface->rect.top,
bits, info, DIB_RGB_COLORS, 0, 0, FALSE, NULL );
window_surface_unlock( old_surface );
NtUserReleaseDC( hwnd, hdc );
}
/***********************************************************************
* move_window_bits_parent
*
@ -1257,30 +1267,18 @@ void move_window_bits( HWND hwnd, struct window_surface *old_surface,
*/
void move_window_bits_parent( HWND hwnd, HWND parent, const RECT *window_rect, const RECT *valid_rects )
{
struct window_surface *surface;
RECT dst = valid_rects[0];
RECT src = valid_rects[1];
WND *win;
if (src.left == dst.left && src.top == dst.top) return;
if (!(win = get_win_ptr( parent ))) return;
if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) return;
if (!(surface = win->surface))
if (src.left != dst.left || src.top != dst.top)
{
release_win_ptr( win );
return;
TRACE( "copying %s -> %s\n", wine_dbgstr_rect( &src ), wine_dbgstr_rect( &dst ));
map_window_points( NtUserGetAncestor( hwnd, GA_PARENT ), parent, (POINT *)&src, 2, get_thread_dpi() );
OffsetRect( &src, -window_rect->left, -window_rect->top );
OffsetRect( &dst, -window_rect->left, -window_rect->top );
copy_bits_from_surface( hwnd, &dst, &src );
}
TRACE( "copying %s -> %s\n", wine_dbgstr_rect( &src ), wine_dbgstr_rect( &dst ));
map_window_points( NtUserGetAncestor( hwnd, GA_PARENT ), parent, (POINT *)&src, 2, get_thread_dpi() );
OffsetRect( &src, -window_rect->left, -window_rect->top );
OffsetRect( &dst, -window_rect->left, -window_rect->top );
window_surface_add_ref( surface );
release_win_ptr( win );
copy_bits_from_surface( hwnd, surface, &dst, &src, TRUE );
window_surface_release( surface );
}
/***********************************************************************

View file

@ -49,10 +49,10 @@ extern void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect
struct window_surface **surface );
extern void erase_now( HWND hwnd, UINT rdw_flags );
extern void flush_window_surfaces( BOOL idle );
extern void move_window_bits( HWND hwnd, struct window_surface *old_surface,
struct window_surface *new_surface,
const RECT *visible_rect, const RECT *old_visible_rect,
extern void move_window_bits( HWND hwnd, const RECT *visible_rect, const RECT *old_visible_rect,
const RECT *window_rect, const RECT *valid_rects );
extern void move_window_bits_surface( HWND hwnd, const RECT *window_rect, struct window_surface *old_surface,
const RECT *old_visible_rect, const RECT *valid_rects );
extern void move_window_bits_parent( HWND hwnd, HWND parent, const RECT *window_rect,
const RECT *valid_rects );
extern void register_window_surface( struct window_surface *old,

View file

@ -1929,8 +1929,10 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
{
if (valid_rects)
{
move_window_bits( hwnd, old_surface, new_surface, &visible_rect,
&old_visible_rect, window_rect, valid_rects );
if (old_surface != new_surface)
move_window_bits_surface( hwnd, window_rect, old_surface, &old_visible_rect, valid_rects );
else
move_window_bits( hwnd, &visible_rect, &old_visible_rect, window_rect, valid_rects );
valid_rects = NULL; /* prevent the driver from trying to also move the bits */
}
window_surface_release( old_surface );