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 */