-- v2: win32u: Use a helper to set the window surface clipping, within the lock. wineandroid: Remove now unnecessary set_surface_region calls. server: Update window surface regions when the window is shaped. win32u: Intersect the clipping region with the window shape region. server: Merge get_surface_region / get_window_region requests together. server: Split update_surface_region into get_window_region helper. win32u: Initialize window surfaces with a hwnd.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 21 ++++++++++++++------- dlls/win32u/win32u_private.h | 2 +- dlls/win32u/window.c | 2 +- dlls/wineandroid.drv/window.c | 12 +++++------- dlls/winemac.drv/macdrv.h | 2 +- dlls/winemac.drv/surface.c | 4 ++-- dlls/winemac.drv/window.c | 4 ++-- dlls/winewayland.drv/window_surface.c | 7 ++----- dlls/winex11.drv/bitblt.c | 4 ++-- dlls/winex11.drv/window.c | 4 ++-- dlls/winex11.drv/x11drv.h | 2 +- include/wine/gdi_driver.h | 3 ++- 12 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index d8a26b655ef..428b25d3b6e 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -98,7 +98,13 @@ static const struct window_surface_funcs dummy_surface_funcs = dummy_surface_destroy };
-struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 }, PTHREAD_MUTEX_INITIALIZER }; +struct window_surface dummy_surface = +{ + .funcs = &dummy_surface_funcs, + .ref = 1, + .rect = {.right = 1, .bottom = 1}, + .mutex = PTHREAD_MUTEX_INITIALIZER, +};
/******************************************************************* * Off-screen window surface. @@ -149,13 +155,13 @@ static const struct window_surface_funcs offscreen_window_surface_funcs = offscreen_window_surface_destroy };
-void create_offscreen_window_surface( const RECT *visible_rect, struct window_surface **surface ) +void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struct window_surface **surface ) { struct offscreen_window_surface *impl; SIZE_T size; RECT surface_rect = *visible_rect;
- TRACE( "visible_rect %s, surface %p.\n", wine_dbgstr_rect( visible_rect ), surface ); + TRACE( "hwnd %p, visible_rect %s, surface %p.\n", hwnd, wine_dbgstr_rect( visible_rect ), surface );
OffsetRect( &surface_rect, -surface_rect.left, -surface_rect.top ); surface_rect.right = (surface_rect.right + 0x1f) & ~0x1f; @@ -174,7 +180,7 @@ void create_offscreen_window_surface( const RECT *visible_rect, struct window_su *surface = NULL; size = surface_rect.right * surface_rect.bottom * 4; if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return; - window_surface_init( &impl->header, &offscreen_window_surface_funcs, &surface_rect ); + window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, &surface_rect );
impl->bits = (char *)&impl->info.bmiColors[0]; impl->info.bmiHeader.biSize = sizeof( impl->info ); @@ -192,10 +198,11 @@ void create_offscreen_window_surface( const RECT *visible_rect, struct window_su
/* window surface common helpers */
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, const RECT *rect ) +W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ) { surface->funcs = funcs; surface->ref = 1; + surface->hwnd = hwnd; surface->rect = *rect; pthread_mutex_init( &surface->mutex, NULL ); reset_bounds( &surface->bounds ); @@ -236,8 +243,8 @@ W32KAPI void window_surface_flush( struct window_surface *surface )
if (intersect_rect( &dirty, &dirty, &surface->bounds )) { - TRACE( "Flushing surface %p %s, bounds %s, dirty %s\n", surface, wine_dbgstr_rect( &surface->rect ), - wine_dbgstr_rect( &surface->bounds ), wine_dbgstr_rect( &dirty ) ); + TRACE( "Flushing hwnd %p, surface %p %s, bounds %s, dirty %s\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ), wine_dbgstr_rect( &surface->bounds ), wine_dbgstr_rect( &dirty ) ); if (surface->funcs->flush( surface, &surface->rect, &dirty )) reset_bounds( &surface->bounds ); }
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index aecd60bae63..8aed662d2d8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -45,7 +45,7 @@ extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param );
/* dce.c */ extern struct window_surface dummy_surface; -extern void create_offscreen_window_surface( const RECT *visible_rect, +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 ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b0fe0218da5..bafceb1a22a 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1814,7 +1814,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, { window_surface_release( new_surface ); if ((new_surface = win->surface)) window_surface_add_ref( new_surface ); - create_offscreen_window_surface( &visible_rect, &new_surface ); + create_offscreen_window_surface( hwnd, &visible_rect, &new_surface ); }
old_visible_rect = win->visible_rect; diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index ddb46c0d4cd..61ebc097f47 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -571,7 +571,6 @@ static int wait_events( int timeout ) struct android_window_surface { struct window_surface header; - HWND hwnd; ANativeWindow *window; BOOL byteswap; RGNDATA *region_data; @@ -656,7 +655,7 @@ static void android_surface_set_region( struct window_surface *window_surface, H { struct android_window_surface *surface = get_android_surface( window_surface );
- TRACE( "updating surface %p hwnd %p with %p\n", surface, surface->hwnd, region ); + TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region );
window_surface_lock( window_surface ); if (!region) @@ -738,7 +737,7 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const surface->window->perform( surface->window, NATIVE_WINDOW_UNLOCK_AND_POST ); } else TRACE( "Unable to lock surface %p window %p buffer %p\n", - surface, surface->hwnd, surface->window ); + surface, window_surface->hwnd, surface->window );
return TRUE; } @@ -806,7 +805,7 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_
if (window_surface->funcs != &android_surface_funcs) return; /* we may get the null surface */
- if (!(win_data = get_win_data( surface->hwnd ))) return; + if (!(win_data = get_win_data( window_surface->hwnd ))) return; offset_x = win_data->window_rect.left - win_data->whole_rect.left; offset_y = win_data->window_rect.top - win_data->whole_rect.top; release_win_data( win_data ); @@ -815,7 +814,7 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_ { region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left, win_data->window_rect.bottom - win_data->window_rect.top ); - if (NtUserGetWindowRgnEx( surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; + if (NtUserGetWindowRgnEx( window_surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; }
NtGdiOffsetRgn( region, offset_x, offset_y ); @@ -850,7 +849,7 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect,
surface = calloc( 1, FIELD_OFFSET( struct android_window_surface, info.bmiColors[3] )); if (!surface) return NULL; - window_surface_init( &surface->header, &android_surface_funcs, rect ); + window_surface_init( &surface->header, &android_surface_funcs, hwnd, rect );
set_color_info( &surface->info, src_alpha ); surface->info.bmiHeader.biWidth = width; @@ -858,7 +857,6 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->info.bmiHeader.biPlanes = 1; surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info );
- surface->hwnd = hwnd; surface->window = get_ioctl_window( hwnd ); surface->alpha = alpha; set_color_key( surface, color_key ); diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index d1101a4a228..a7905050f16 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -208,7 +208,7 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p extern macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen); extern RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp); extern void activate_on_following_focus(void); -extern struct window_surface *create_surface(macdrv_window window, const RECT *rect, +extern struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha); extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha); extern void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect); diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 7e296f33a62..a6f61538d16 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -149,7 +149,7 @@ static struct macdrv_window_surface *get_mac_surface(struct window_surface *surf /*********************************************************************** * create_surface */ -struct window_surface *create_surface(macdrv_window window, const RECT *rect, +struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha) { struct macdrv_window_surface *surface; @@ -159,7 +159,7 @@ struct window_surface *create_surface(macdrv_window window, const RECT *rect,
surface = calloc(1, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])); if (!surface) return NULL; - window_surface_init(&surface->header, &macdrv_surface_funcs, rect); + window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, rect);
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 04eb6d00860..84668b44c51 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1915,7 +1915,7 @@ BOOL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, surface = data->surface; if (!surface || !EqualRect(&surface->rect, &rect)) { - data->surface = create_surface(data->cocoa_window, &rect, NULL, TRUE); + data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE); macdrv_set_window_surface(data->cocoa_window, data->surface); if (surface) window_surface_release(surface); surface = data->surface; @@ -2094,7 +2094,7 @@ BOOL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags, } else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
- *surface = create_surface(data->cocoa_window, &surface_rect, data->surface, FALSE); + *surface = create_surface(data->hwnd, data->cocoa_window, &surface_rect, data->surface, FALSE);
done: release_win_data(data); diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 2605b3c7b3d..2c19c8ffdc4 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; - HWND hwnd; struct wayland_surface *wayland_surface; struct wayland_buffer_queue *wayland_buffer_queue; void *bits; @@ -463,7 +462,7 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect
wws = calloc(1, sizeof(*wws)); if (!wws) return NULL; - window_surface_init(&wws->header, &wayland_window_surface_funcs, rect); + window_surface_init(&wws->header, &wayland_window_surface_funcs, hwnd, rect);
wws->info.bmiHeader.biSize = sizeof(wws->info.bmiHeader); wws->info.bmiHeader.biClrUsed = 0; @@ -474,8 +473,6 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect wws->info.bmiHeader.biPlanes = 1; wws->info.bmiHeader.biSizeImage = width * height * 4;
- wws->hwnd = hwnd; - if (!(wws->bits = malloc(wws->info.bmiHeader.biSizeImage))) goto failed;
@@ -499,7 +496,7 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *window
window_surface_lock(window_surface);
- TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, wws->hwnd, wayland_surface); + TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, window_surface->hwnd, wayland_surface);
wws->wayland_surface = wayland_surface;
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index f0d523b6f9c..404beab923d 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1954,7 +1954,7 @@ static const struct window_surface_funcs x11drv_surface_funcs = /*********************************************************************** * create_surface */ -struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect, +struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect, COLORREF color_key, BOOL use_alpha ) { const XPixmapFormatValues *format = pixmap_formats[vis->depth]; @@ -1964,7 +1964,7 @@ struct window_surface *create_surface( Window window, const XVisualInfo *vis, co
surface = calloc( 1, FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] )); if (!surface) return NULL; - window_surface_init( &surface->header, &x11drv_surface_funcs, rect ); + window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, rect );
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 823a17e3998..f975986a9d9 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2645,7 +2645,7 @@ BOOL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, if (!layered || !NtUserGetLayeredWindowAttributes( hwnd, &key, NULL, &flags ) || !(flags & LWA_COLORKEY)) key = CLR_INVALID;
- *surface = create_surface( data->whole_window, &data->vis, &surface_rect, key, FALSE ); + *surface = create_surface( data->hwnd, data->whole_window, &data->vis, &surface_rect, key, FALSE );
done: release_win_data( data ); @@ -2991,7 +2991,7 @@ BOOL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, surface = data->surface; if (!surface || !EqualRect( &surface->rect, &rect )) { - data->surface = create_surface( data->whole_window, &data->vis, &rect, + data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, &rect, color_key, data->use_alpha ); if (surface) window_surface_release( surface ); surface = data->surface; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d10ade448e2..2a326b07a4c 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -265,7 +265,7 @@ extern Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const B const struct gdi_image_bits *bits, UINT coloruse ); extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis, BITMAPINFO *info, struct gdi_image_bits *bits ); -extern struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect, +extern struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect, COLORREF color_key, BOOL use_alpha ); extern void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key ); extern HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ); diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 2721083c6ad..f6cfc7778de 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -222,6 +222,7 @@ struct window_surface const struct window_surface_funcs *funcs; /* driver-specific implementations */ struct list entry; /* entry in global list managed by user32 */ LONG ref; /* reference count */ + HWND hwnd; /* window the surface was created for */ RECT rect; /* constant, no locking needed */
pthread_mutex_t mutex; @@ -230,7 +231,7 @@ struct window_surface /* driver-specific fields here */ };
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, const RECT *rect ); +W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ); W32KAPI void window_surface_add_ref( struct window_surface *surface ); W32KAPI void window_surface_release( struct window_surface *surface ); W32KAPI void window_surface_lock( struct window_surface *surface );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index bafceb1a22a..ee0d3001762 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1717,23 +1717,16 @@ static BOOL get_window_info( HWND hwnd, WINDOWINFO *info ) return TRUE; }
-/*********************************************************************** - * update_surface_region - */ -static void update_surface_region( HWND hwnd ) +static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) { NTSTATUS status; - HRGN region = 0; RGNDATA *data; size_t size = 256; - WND *win = get_win_ptr( hwnd ); - - if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; - if (!win->surface) goto done;
+ *region = 0; do { - if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) goto done; + if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) return STATUS_NO_MEMORY;
SERVER_START_REQ( get_surface_region ) { @@ -1748,20 +1741,38 @@ static void update_surface_region( HWND hwnd ) data->rdh.iType = RDH_RECTANGLES; data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nRgnSize = reply_size; - region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiOffsetRgn( region, -reply->visible_rect.left, -reply->visible_rect.top ); + *region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); + NtGdiOffsetRgn( *region, -reply->visible_rect.left, -reply->visible_rect.top ); } } else size = reply->total_size; } SERVER_END_REQ; + free( data ); } while (status == STATUS_BUFFER_OVERFLOW);
- if (status) goto done; + return status; +}
- win->surface->funcs->set_region( win->surface, region ); - if (region) NtGdiDeleteObjectApp( region ); +/*********************************************************************** + * update_surface_region + */ +static void update_surface_region( HWND hwnd ) +{ + WND *win = get_win_ptr( hwnd ); + HRGN region; + + if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; + if (!win->surface) goto done; + + if (get_window_region( hwnd, ®ion )) goto done; + if (!region) win->surface->funcs->set_region( win->surface, 0 ); + else + { + win->surface->funcs->set_region( win->surface, region ); + NtGdiDeleteObjectApp( region ); + }
done: release_win_ptr( win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 52 +++++++++++++++----------------------------- server/protocol.def | 12 ++-------- server/window.c | 30 ++++++++++++------------- 3 files changed, 33 insertions(+), 61 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index ee0d3001762..4d310edcbb2 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1717,7 +1717,7 @@ static BOOL get_window_info( HWND hwnd, WINDOWINFO *info ) return TRUE; }
-static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) +static NTSTATUS get_window_region( HWND hwnd, BOOL surface, HRGN *region, RECT *visible ) { NTSTATUS status; RGNDATA *data; @@ -1728,9 +1728,10 @@ static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) { if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) return STATUS_NO_MEMORY;
- SERVER_START_REQ( get_surface_region ) + SERVER_START_REQ( get_window_region ) { req->window = wine_server_user_handle( hwnd ); + req->surface = surface; wine_server_set_reply( req, data->Buffer, size ); if (!(status = wine_server_call( req ))) { @@ -1742,7 +1743,10 @@ static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nRgnSize = reply_size; *region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiOffsetRgn( *region, -reply->visible_rect.left, -reply->visible_rect.top ); + visible->left = reply->visible_rect.left; + visible->top = reply->visible_rect.top; + visible->right = reply->visible_rect.right; + visible->bottom = reply->visible_rect.bottom; } } else size = reply->total_size; @@ -1762,14 +1766,16 @@ static void update_surface_region( HWND hwnd ) { WND *win = get_win_ptr( hwnd ); HRGN region; + RECT visible;
if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; if (!win->surface) goto done;
- if (get_window_region( hwnd, ®ion )) goto done; + if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; if (!region) win->surface->funcs->set_region( win->surface, 0 ); else { + NtGdiOffsetRgn( region, -visible.left, -visible.top ); win->surface->funcs->set_region( win->surface, region ); NtGdiDeleteObjectApp( region ); } @@ -1959,41 +1965,17 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, int WINAPI NtUserGetWindowRgnEx( HWND hwnd, HRGN hrgn, UINT unk ) { NTSTATUS status; - HRGN win_rgn = 0; - RGNDATA *data; - size_t size = 256; int ret = ERROR; + HRGN win_rgn; + RECT visible;
- do + if ((status = get_window_region( hwnd, FALSE, &win_rgn, &visible ))) { - if (!(data = malloc( sizeof(*data) + size - 1 ))) - { - RtlSetLastWin32Error( ERROR_OUTOFMEMORY ); - return ERROR; - } - SERVER_START_REQ( get_window_region ) - { - req->window = wine_server_user_handle( hwnd ); - wine_server_set_reply( req, data->Buffer, size ); - if (!(status = wine_server_call( req ))) - { - size_t reply_size = wine_server_reply_size( reply ); - if (reply_size) - { - data->rdh.dwSize = sizeof(data->rdh); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = reply_size / sizeof(RECT); - data->rdh.nRgnSize = reply_size; - win_rgn = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - } - } - else size = reply->total_size; - } - SERVER_END_REQ; - free( data ); - } while (status == STATUS_BUFFER_OVERFLOW); + set_ntstatus( status ); + return ERROR; + }
- if (set_ntstatus( status ) && win_rgn) + if (win_rgn) { ret = NtGdiCombineRgn( hrgn, win_rgn, 0, RGN_COPY ); NtGdiDeleteObjectApp( win_rgn ); diff --git a/server/protocol.def b/server/protocol.def index 1491994197c..ac103156fe4 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2592,20 +2592,12 @@ enum coords_relative @END
-/* Get the visible surface region of a window */ -@REQ(get_surface_region) - user_handle_t window; /* handle to the window */ -@REPLY - rectangle_t visible_rect; /* window visible rect in screen coords */ - data_size_t total_size; /* total size of the resulting region */ - VARARG(region,rectangles); /* list of rectangles for the region (in screen coords) */ -@END - - /* Get the window region */ @REQ(get_window_region) user_handle_t window; /* handle to the window */ + int surface; /* get the visible surface region */ @REPLY + rectangle_t visible_rect; /* window visible rect in screen coords */ data_size_t total_size; /* total size of the resulting region */ VARARG(region,rectangles); /* list of rectangles for the region (in window coords) */ @END diff --git a/server/window.c b/server/window.c index b98429c8f31..50d6ae5dbcc 100644 --- a/server/window.c +++ b/server/window.c @@ -2631,30 +2631,28 @@ DECL_HANDLER(get_visible_region) }
-/* get the surface visible region of a window */ -DECL_HANDLER(get_surface_region) +/* get the window regions */ +DECL_HANDLER(get_window_region) { + rectangle_t *data; struct region *region; struct window *win = get_window( req->window );
- if (!win || !is_visible( win )) return; + if (!win) return;
- if ((region = get_surface_region( win ))) - { - rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); - if (data) set_reply_data_ptr( data, reply->total_size ); - } reply->visible_rect = win->visible_rect; -} - + if (req->surface) + { + if (!is_visible( win )) return;
-/* get the window region */ -DECL_HANDLER(get_window_region) -{ - rectangle_t *data; - struct window *win = get_window( req->window ); + if ((region = get_surface_region( win ))) + { + rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); + if (data) set_reply_data_ptr( data, reply->total_size ); + } + return; + }
- if (!win) return; if (!win->win_region) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4d310edcbb2..ea4399b4293 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1765,22 +1765,33 @@ static NTSTATUS get_window_region( HWND hwnd, BOOL surface, HRGN *region, RECT * static void update_surface_region( HWND hwnd ) { WND *win = get_win_ptr( hwnd ); - HRGN region; + HRGN region, shape = 0; RECT visible;
if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; if (!win->surface) goto done;
+ if (get_window_region( hwnd, FALSE, &shape, &visible )) goto done; + if (shape) + { + region = NtGdiCreateRectRgn( 0, 0, visible.right - visible.left, visible.bottom - visible.top ); + NtGdiCombineRgn( shape, shape, region, RGN_AND ); + if (win->dwExStyle & WS_EX_LAYOUTRTL) NtUserMirrorRgn( hwnd, shape ); + NtGdiDeleteObjectApp( region ); + } + if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; - if (!region) win->surface->funcs->set_region( win->surface, 0 ); + if (!region) win->surface->funcs->set_region( win->surface, shape ); else { NtGdiOffsetRgn( region, -visible.left, -visible.top ); + if (shape) NtGdiCombineRgn( region, region, shape, RGN_AND ); win->surface->funcs->set_region( win->surface, region ); NtGdiDeleteObjectApp( region ); }
done: + if (shape) NtGdiDeleteObjectApp( shape ); release_win_ptr( win ); }
From: Rémi Bernon rbernon@codeweavers.com
--- server/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/window.c b/server/window.c index 50d6ae5dbcc..4ebfec3da12 100644 --- a/server/window.c +++ b/server/window.c @@ -2485,7 +2485,8 @@ DECL_HANDLER(set_window_pos) if (is_visible( top ) && (top->paint_flags & PAINT_HAS_SURFACE)) { reply->surface_win = top->handle; - reply->needs_update = !!(top->paint_flags & (PAINT_HAS_PIXEL_FORMAT | PAINT_PIXEL_FORMAT_CHILD)); + reply->needs_update = !!(top->paint_flags & (PAINT_HAS_PIXEL_FORMAT | PAINT_PIXEL_FORMAT_CHILD)) || + !!top->win_region; } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/wineandroid.drv/android.h | 1 - dlls/wineandroid.drv/init.c | 1 - dlls/wineandroid.drv/window.c | 81 ++++++---------------------------- 3 files changed, 14 insertions(+), 69 deletions(-)
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index e793d103788..2512976089b 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -95,7 +95,6 @@ extern LRESULT ANDROID_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM extern void ANDROID_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); extern void ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent ); -extern void ANDROID_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ); extern void ANDROID_SetCapture( HWND hwnd, UINT flags ); extern void ANDROID_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ); extern UINT ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index d48c4153b06..5b4ec59d2fa 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -346,7 +346,6 @@ static const struct user_driver_funcs android_drv_funcs = .pSetCapture = ANDROID_SetCapture, .pSetLayeredWindowAttributes = ANDROID_SetLayeredWindowAttributes, .pSetParent = ANDROID_SetParent, - .pSetWindowRgn = ANDROID_SetWindowRgn, .pSetWindowStyle = ANDROID_SetWindowStyle, .pShowWindow = ANDROID_ShowWindow, .pUpdateLayeredWindow = ANDROID_UpdateLayeredWindow, diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 61ebc097f47..d04649da69f 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -70,8 +70,6 @@ static inline int context_idx( HWND hwnd ) return LOWORD( hwnd ) >> 1; }
-static void set_surface_region( struct window_surface *window_surface, HRGN win_region ); - /* only for use on sanitized BITMAPINFO structures */ static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse ) { @@ -654,6 +652,8 @@ static void *android_surface_get_bitmap_info( struct window_surface *window_surf static void android_surface_set_region( struct window_surface *window_surface, HRGN region ) { struct android_window_surface *surface = get_android_surface( window_surface ); + RGNDATA *data; + UINT size;
TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region );
@@ -668,8 +668,19 @@ static void android_surface_set_region( struct window_surface *window_surface, H if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); } + + if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; + if (!(data = malloc( size ))) goto done; + if (!NtGdiGetRegionData( region, size, data )) + { + free( data ); + data = NULL; + } + free( surface->region_data ); + surface->region_data = data; + +done: window_surface_unlock( window_surface ); - set_surface_region( &surface->header, (HRGN)1 ); }
/*********************************************************************** @@ -791,53 +802,6 @@ static void set_color_key( struct android_window_surface *surface, COLORREF key surface->color_key = (GetRValue(key) << 16) | (GetGValue(key) << 8) | GetBValue(key); }
-/*********************************************************************** - * set_surface_region - */ -static void set_surface_region( struct window_surface *window_surface, HRGN win_region ) -{ - struct android_window_surface *surface = get_android_surface( window_surface ); - struct android_win_data *win_data; - HRGN region = win_region; - RGNDATA *data = NULL; - DWORD size; - int offset_x, offset_y; - - if (window_surface->funcs != &android_surface_funcs) return; /* we may get the null surface */ - - if (!(win_data = get_win_data( window_surface->hwnd ))) return; - offset_x = win_data->window_rect.left - win_data->whole_rect.left; - offset_y = win_data->window_rect.top - win_data->whole_rect.top; - release_win_data( win_data ); - - if (win_region == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */ - { - region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left, - win_data->window_rect.bottom - win_data->window_rect.top ); - if (NtUserGetWindowRgnEx( window_surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; - } - - NtGdiOffsetRgn( region, offset_x, offset_y ); - if (surface->region) NtGdiCombineRgn( region, region, surface->region, RGN_AND ); - - if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; - if (!(data = malloc( size ))) goto done; - - if (!NtGdiGetRegionData( region, size, data )) - { - free( data ); - data = NULL; - } - -done: - window_surface_lock( window_surface ); - free( surface->region_data ); - surface->region_data = data; - window_surface->bounds = surface->header.rect; - window_surface_unlock( window_surface ); - if (region != win_region) NtGdiDeleteObjectApp( region ); -} - /*********************************************************************** * create_surface */ @@ -860,7 +824,6 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->window = get_ioctl_window( hwnd ); surface->alpha = alpha; set_color_key( surface, color_key ); - set_surface_region( &surface->header, (HRGN)1 );
if (!(surface->bits = malloc( surface->info.bmiHeader.biSizeImage ))) goto failed; @@ -1435,22 +1398,6 @@ void ANDROID_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) }
-/*********************************************************************** - * ANDROID_SetWindowRgn - */ -void ANDROID_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) -{ - struct android_win_data *data; - - if ((data = get_win_data( hwnd ))) - { - if (data->surface) set_surface_region( data->surface, hrgn ); - release_win_data( data ); - } - else FIXME( "not supported on other process window %p\n", hwnd ); -} - - /*********************************************************************** * ANDROID_SetLayeredWindowAttributes */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 42 ++++++++++++++++++-- dlls/win32u/window.c | 4 +- dlls/wineandroid.drv/window.c | 52 ++++++------------------- dlls/winemac.drv/surface.c | 26 ++----------- dlls/winewayland.drv/window_surface.c | 8 ++-- dlls/winex11.drv/bitblt.c | 55 ++++++++++++++------------- include/wine/gdi_driver.h | 4 +- 7 files changed, 91 insertions(+), 100 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 428b25d3b6e..02b11db4dd5 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -74,7 +74,7 @@ static void *dummy_surface_get_bitmap_info( struct window_surface *window_surfac return &dummy_data; }
-static void dummy_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void dummy_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { /* nothing to do */ } @@ -93,7 +93,7 @@ static void dummy_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs dummy_surface_funcs = { dummy_surface_get_bitmap_info, - dummy_surface_set_region, + dummy_surface_set_clip, dummy_surface_flush, dummy_surface_destroy }; @@ -132,7 +132,7 @@ static void *offscreen_window_surface_get_bitmap_info( struct window_surface *ba return impl->bits; }
-static void offscreen_window_surface_set_region( struct window_surface *base, HRGN region ) +static void offscreen_window_surface_set_clip( struct window_surface *base, const RECT *rects, UINT count ) { }
@@ -150,7 +150,7 @@ static void offscreen_window_surface_destroy( struct window_surface *base ) static const struct window_surface_funcs offscreen_window_surface_funcs = { offscreen_window_surface_get_bitmap_info, - offscreen_window_surface_set_region, + offscreen_window_surface_set_clip, offscreen_window_surface_flush, offscreen_window_surface_destroy }; @@ -219,6 +219,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ) if (!ret) { if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex ); + if (surface->clip_region) NtGdiDeleteObjectApp( surface->clip_region ); surface->funcs->destroy( surface ); } } @@ -251,6 +252,39 @@ W32KAPI void window_surface_flush( struct window_surface *surface ) window_surface_unlock( surface ); }
+W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_region ) +{ + window_surface_lock( surface ); + + if (!clip_region && surface->clip_region) + { + TRACE( "hwnd %p, surface %p %s, clearing clip region\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ) ); + + NtGdiDeleteObjectApp( surface->clip_region ); + surface->clip_region = 0; + surface->funcs->set_clip( surface, NULL, 0 ); + } + else if (clip_region && !NtGdiEqualRgn( clip_region, surface->clip_region )) + { + WINEREGION *data; + + TRACE( "hwnd %p, surface %p %s, setting clip region %p\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ), clip_region ); + + if (!surface->clip_region) surface->clip_region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + NtGdiCombineRgn( surface->clip_region, clip_region, 0, RGN_COPY ); + + if ((data = GDI_GetObjPtr( clip_region, NTGDI_OBJ_REGION ))) + { + surface->funcs->set_clip( surface, data->rects, data->numRects ); + GDI_ReleaseObj( clip_region ); + } + } + + window_surface_unlock( surface ); +} + /******************************************************************* * register_window_surface * diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index ea4399b4293..12f2a9027f0 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1781,12 +1781,12 @@ static void update_surface_region( HWND hwnd ) }
if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; - if (!region) win->surface->funcs->set_region( win->surface, shape ); + if (!region) window_surface_set_clip( win->surface, shape ); else { NtGdiOffsetRgn( region, -visible.left, -visible.top ); if (shape) NtGdiCombineRgn( region, region, shape, RGN_AND ); - win->surface->funcs->set_region( win->surface, region ); + window_surface_set_clip( win->surface, region ); NtGdiDeleteObjectApp( region ); }
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index d04649da69f..de1de330181 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -571,8 +571,8 @@ struct android_window_surface struct window_surface header; ANativeWindow *window; BOOL byteswap; - RGNDATA *region_data; - HRGN region; + UINT clip_count; + RECT *clip_rects; BYTE alpha; COLORREF color_key; void *bits; @@ -647,40 +647,18 @@ static void *android_surface_get_bitmap_info( struct window_surface *window_surf }
/*********************************************************************** - * android_surface_set_region + * android_surface_set_clip */ -static void android_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void android_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { struct android_window_surface *surface = get_android_surface( window_surface ); - RGNDATA *data; - UINT size;
- TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region ); + free( surface->clip_rects ); + surface->clip_rects = NULL;
- window_surface_lock( window_surface ); - if (!region) - { - if (surface->region) NtGdiDeleteObjectApp( surface->region ); - surface->region = 0; - } - else - { - if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); - } - - if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; - if (!(data = malloc( size ))) goto done; - if (!NtGdiGetRegionData( region, size, data )) - { - free( data ); - data = NULL; - } - free( surface->region_data ); - surface->region_data = data; - -done: - window_surface_unlock( window_surface ); + if (!count || !(surface->clip_rects = malloc( count * sizeof(*rects) ))) return; + memcpy( surface->clip_rects, rects, count * sizeof(*rects) ); + surface->clip_count = count; }
/*********************************************************************** @@ -699,7 +677,7 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const
if (!surface->window->perform( surface->window, NATIVE_WINDOW_LOCK, &buffer, &rc )) { - const RECT *rgn_rect = NULL, *end = NULL; + const RECT *rgn_rect = surface->clip_rects, *end = surface->clip_rects + surface->clip_count; DWORD *src, *dst; int x, y, width; RECT locked; @@ -710,11 +688,6 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const locked.bottom = rc.bottom; intersect_rect( &locked, &locked, rect );
- if (surface->region_data) - { - rgn_rect = (RECT *)surface->region_data->Buffer; - end = rgn_rect + surface->region_data->rdh.nCount; - } src = (DWORD *)surface->bits + (locked.top - rect->top) * surface->info.bmiHeader.biWidth + (locked.left - rect->left); dst = (DWORD *)buffer.bits + locked.top * buffer.stride + locked.left; @@ -762,8 +735,7 @@ static void android_surface_destroy( struct window_surface *window_surface )
TRACE( "freeing %p bits %p\n", surface, surface->bits );
- free( surface->region_data ); - if (surface->region) NtGdiDeleteObjectApp( surface->region ); + free( surface->clip_rects ); release_ioctl_window( surface->window ); free( surface->bits ); free( surface ); @@ -772,7 +744,7 @@ static void android_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs android_surface_funcs = { android_surface_get_bitmap_info, - android_surface_set_region, + android_surface_set_clip, android_surface_flush, android_surface_destroy }; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index a6f61538d16..285561e6d02 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -64,7 +64,6 @@ struct macdrv_window_surface { struct window_surface header; macdrv_window window; - HRGN region; BOOL use_alpha; BYTE *bits; BITMAPINFO info; /* variable size, must be last */ @@ -85,28 +84,10 @@ static void *macdrv_surface_get_bitmap_info(struct window_surface *window_surfac }
/*********************************************************************** - * macdrv_surface_set_region + * macdrv_surface_set_clip */ -static void macdrv_surface_set_region(struct window_surface *window_surface, HRGN region) +static void macdrv_surface_set_clip(struct window_surface *window_surface, const RECT *rects, UINT count) { - struct macdrv_window_surface *surface = get_mac_surface(window_surface); - - TRACE("updating surface %p with %p\n", surface, region); - - window_surface_lock(window_surface); - - if (region) - { - if (!surface->region) surface->region = NtGdiCreateRectRgn(0, 0, 0, 0); - NtGdiCombineRgn(surface->region, region, 0, RGN_COPY); - } - else - { - if (surface->region) NtGdiDeleteObjectApp(surface->region); - surface->region = 0; - } - - window_surface_unlock(window_surface); }
/*********************************************************************** @@ -127,7 +108,6 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) struct macdrv_window_surface *surface = get_mac_surface(window_surface);
TRACE("freeing %p bits %p\n", surface, surface->bits); - if (surface->region) NtGdiDeleteObjectApp(surface->region); free(surface->bits); free(surface); } @@ -135,7 +115,7 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) static const struct window_surface_funcs macdrv_surface_funcs = { macdrv_surface_get_bitmap_info, - macdrv_surface_set_region, + macdrv_surface_set_clip, macdrv_surface_flush, macdrv_surface_destroy, }; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 2c19c8ffdc4..752a560ddec 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -224,10 +224,10 @@ static void *wayland_window_surface_get_bitmap_info(struct window_surface *windo }
/*********************************************************************** - * wayland_window_surface_set_region + * wayland_window_surface_set_clip */ -static void wayland_window_surface_set_region(struct window_surface *window_surface, - HRGN region) +static void wayland_window_surface_set_clip(struct window_surface *window_surface, + const RECT *rects, UINT count) { /* TODO */ } @@ -444,7 +444,7 @@ static void wayland_window_surface_destroy(struct window_surface *window_surface static const struct window_surface_funcs wayland_window_surface_funcs = { wayland_window_surface_get_bitmap_info, - wayland_window_surface_set_region, + wayland_window_surface_set_clip, wayland_window_surface_flush, wayland_window_surface_destroy }; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 404beab923d..df8fc8f1257 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1581,7 +1581,6 @@ struct x11drv_window_surface BOOL is_argb; DWORD alpha_bits; COLORREF color_key; - HRGN region; void *bits; #ifdef HAVE_LIBXXSHM XShmSegmentInfo shminfo; @@ -1837,35 +1836,41 @@ static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surfa return surface->bits; }
+static XRectangle *xrectangles_from_rects( const RECT *rects, UINT count ) +{ + XRectangle *xrects; + if (!(xrects = malloc( count * sizeof(*xrects) ))) return NULL; + while (count--) + { + if (rects[count].left > SHRT_MAX) continue; + if (rects[count].top > SHRT_MAX) continue; + if (rects[count].right < SHRT_MIN) continue; + if (rects[count].bottom < SHRT_MIN) continue; + xrects[count].x = max( min( rects[count].left, SHRT_MAX), SHRT_MIN); + xrects[count].y = max( min( rects[count].top, SHRT_MAX), SHRT_MIN); + xrects[count].width = max( min( rects[count].right, SHRT_MAX ) - xrects[count].x, 0); + xrects[count].height = max( min( rects[count].bottom, SHRT_MAX ) - xrects[count].y, 0); + } + return xrects; +} + /*********************************************************************** - * x11drv_surface_set_region + * x11drv_surface_set_clip */ -static void x11drv_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void x11drv_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { - RGNDATA *data; struct x11drv_window_surface *surface = get_x11_surface( window_surface ); + XRectangle *xrects;
- TRACE( "updating surface %p with %p\n", surface, region ); + TRACE( "surface %p, rects %p, count %u\n", surface, rects, count );
- window_surface_lock( window_surface ); - if (!region) - { - if (surface->region) NtGdiDeleteObjectApp( surface->region ); - surface->region = 0; + if (!count) XSetClipMask( gdi_display, surface->gc, None ); - } - else + else if ((xrects = xrectangles_from_rects( rects, count ))) { - if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); - if ((data = X11DRV_GetRegionData( surface->region, 0 ))) - { - XSetClipRectangles( gdi_display, surface->gc, 0, 0, - (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); - free( data ); - } + XSetClipRectangles( gdi_display, surface->gc, 0, 0, xrects, count, YXBanded ); + free( xrects ); } - window_surface_unlock( window_surface ); }
/*********************************************************************** @@ -1938,7 +1943,6 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) surface->image->data = NULL; XDestroyImage( surface->image ); } - if (surface->region) NtGdiDeleteObjectApp( surface->region );
free( surface ); } @@ -1946,7 +1950,7 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs x11drv_surface_funcs = { x11drv_surface_get_bitmap_info, - x11drv_surface_set_region, + x11drv_surface_set_clip, x11drv_surface_flush, x11drv_surface_destroy }; @@ -2038,7 +2042,6 @@ void set_surface_color_key( struct window_surface *window_surface, COLORREF colo */ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) { - struct x11drv_window_surface *surface = get_x11_surface( window_surface ); HRGN region = 0; RECT rc = *rect;
@@ -2047,10 +2050,10 @@ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) window_surface_lock( window_surface ); OffsetRect( &rc, -window_surface->rect.left, -window_surface->rect.top ); add_bounds_rect( &window_surface->bounds, &rc ); - if (surface->region) + if (window_surface->clip_region) { region = NtGdiCreateRectRgn( rect->left, rect->top, rect->right, rect->bottom ); - if (NtGdiCombineRgn( region, region, surface->region, RGN_DIFF ) <= NULLREGION) + if (NtGdiCombineRgn( region, region, window_surface->clip_region, RGN_DIFF ) <= NULLREGION) { NtGdiDeleteObjectApp( region ); region = 0; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index f6cfc7778de..588930f9e01 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -212,7 +212,7 @@ struct window_surface; struct window_surface_funcs { void* (*get_info)( struct window_surface *surface, BITMAPINFO *info ); - void (*set_region)( struct window_surface *surface, HRGN region ); + void (*set_clip)( struct window_surface *surface, const RECT *rects, UINT count ); BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty ); void (*destroy)( struct window_surface *surface ); }; @@ -227,6 +227,7 @@ struct window_surface
pthread_mutex_t mutex; RECT bounds; /* dirty area rect, requires locking */ + HRGN clip_region; /* visible region of the surface, fully visible if 0 */ DWORD draw_start_ticks; /* start ticks of fresh draw */ /* driver-specific fields here */ }; @@ -237,6 +238,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ); W32KAPI void window_surface_lock( struct window_surface *surface ); W32KAPI void window_surface_unlock( struct window_surface *surface ); W32KAPI void window_surface_flush( struct window_surface *surface ); +W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_region );
/* display manager interface, used to initialize display device registry data */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=145942
Your paranoid android.
=== debian11b (64 bit WoW report) ===
wmvcore: wmvcore.c:2831: Test failed: Got pts 3260000. wmvcore.c:2843: Test failed: Got pts 3250000. wmvcore.c:2850: Test failed: Got pts 3260000. wmvcore.c:2862: Test failed: Got pts 3250000.
On Thu May 30 13:19:00 2024 +0000, Rémi Bernon wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5753/diffs?diff_id=115818&start_sha=d0e126f1981b4132bba8a3299dc7c2349d58c898#65bc214e6d025c53e466128853d07366b287855b_1793_1793)
Indeed, thanks.
On Thu May 30 13:19:01 2024 +0000, Rémi Bernon wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5753/diffs?diff_id=115818&start_sha=d0e126f1981b4132bba8a3299dc7c2349d58c898#515f291235626778b5253c80373554036e2a43f0_221_221)
It's not, rather some bad patch rebase, thanks.