From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 27 +++++++-- dlls/win32u/dibdrv/dc.c | 2 +- dlls/wineandroid.drv/window.c | 65 +++++++--------------- dlls/winemac.drv/surface.c | 16 +----- dlls/winemac.drv/window.c | 2 +- dlls/winewayland.drv/window.c | 2 +- dlls/winewayland.drv/window_surface.c | 16 +----- dlls/winex11.drv/bitblt.c | 80 ++++++++++----------------- dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/window.c | 6 +- include/wine/gdi_driver.h | 3 +- 11 files changed, 86 insertions(+), 135 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index a97a21d072c..d8a26b655ef 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -79,9 +79,10 @@ static void dummy_surface_set_region( struct window_surface *window_surface, HRG /* nothing to do */ }
-static void dummy_surface_flush( struct window_surface *window_surface ) +static BOOL dummy_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty ) { /* nothing to do */ + return TRUE; }
static void dummy_surface_destroy( struct window_surface *window_surface ) @@ -129,11 +130,9 @@ static void offscreen_window_surface_set_region( struct window_surface *base, HR { }
-static void offscreen_window_surface_flush( struct window_surface *surface ) +static BOOL offscreen_window_surface_flush( struct window_surface *base, const RECT *rect, const RECT *dirty ) { - window_surface_lock( surface ); - reset_bounds( &surface->bounds ); - window_surface_unlock( surface ); + return TRUE; }
static void offscreen_window_surface_destroy( struct window_surface *base ) @@ -229,6 +228,22 @@ W32KAPI void window_surface_unlock( struct window_surface *surface ) pthread_mutex_unlock( &surface->mutex ); }
+W32KAPI void window_surface_flush( struct window_surface *surface ) +{ + RECT dirty = surface->rect; + + window_surface_lock( 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 ) ); + if (surface->funcs->flush( surface, &surface->rect, &dirty )) reset_bounds( &surface->bounds ); + } + + window_surface_unlock( surface ); +} + /******************************************************************* * register_window_surface * @@ -263,7 +278,7 @@ void flush_window_surfaces( BOOL idle ) else if ((int)(now - last_idle) < 50) goto done;
LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry ) - surface->funcs->flush( surface ); + window_surface_flush( surface ); done: pthread_mutex_unlock( &surfaces_lock ); } diff --git a/dlls/win32u/dibdrv/dc.c b/dlls/win32u/dibdrv/dc.c index 6050923b9c4..48320f5b676 100644 --- a/dlls/win32u/dibdrv/dc.c +++ b/dlls/win32u/dibdrv/dc.c @@ -765,7 +765,7 @@ static inline void unlock_surface( struct windrv_physdev *dev ) { DWORD ticks = NtGetTickCount() - surface->draw_start_ticks; window_surface_unlock( surface ); - if (ticks > FLUSH_PERIOD) surface->funcs->flush( dev->surface ); + if (ticks > FLUSH_PERIOD) window_surface_flush( dev->surface ); } }
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index d1c93b5ceff..ddb46c0d4cd 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -587,12 +587,6 @@ static struct android_window_surface *get_android_surface( struct window_surface return (struct android_window_surface *)surface; }
-static inline void reset_bounds( RECT *bounds ) -{ - bounds->left = bounds->top = INT_MAX; - bounds->right = bounds->bottom = INT_MIN; -} - static inline void add_bounds_rect( RECT *bounds, const RECT *rect ) { if (rect->left >= rect->right || rect->top >= rect->bottom) return; @@ -682,60 +676,41 @@ static void android_surface_set_region( struct window_surface *window_surface, H /*********************************************************************** * android_surface_flush */ -static void android_surface_flush( struct window_surface *window_surface ) +static BOOL android_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty ) { struct android_window_surface *surface = get_android_surface( window_surface ); ANativeWindow_Buffer buffer; ARect rc; - RECT rect; - BOOL needs_flush; - - window_surface_lock( window_surface ); - SetRect( &rect, 0, 0, surface->header.rect.right - surface->header.rect.left, - surface->header.rect.bottom - surface->header.rect.top ); - needs_flush = intersect_rect( &rect, &rect, &window_surface->bounds ); - reset_bounds( &window_surface->bounds ); - - if (!needs_flush) - { - window_surface_unlock( window_surface ); - return; - }
- TRACE( "flushing %p hwnd %p surface %s rect %s bits %p alpha %02x key %08x region %u rects\n", - surface, surface->hwnd, wine_dbgstr_rect( &surface->header.rect ), - wine_dbgstr_rect( &rect ), surface->bits, surface->alpha, (int)surface->color_key, - surface->region_data ? (int)surface->region_data->rdh.nCount : 0 ); - - rc.left = rect.left; - rc.top = rect.top; - rc.right = rect.right; - rc.bottom = rect.bottom; + rc.left = dirty->left; + rc.top = dirty->top; + rc.right = dirty->right; + rc.bottom = dirty->bottom;
if (!surface->window->perform( surface->window, NATIVE_WINDOW_LOCK, &buffer, &rc )) { const RECT *rgn_rect = NULL, *end = NULL; DWORD *src, *dst; int x, y, width; + RECT locked;
- rect.left = rc.left; - rect.top = rc.top; - rect.right = rc.right; - rect.bottom = rc.bottom; - intersect_rect( &rect, &rect, &surface->header.rect ); + locked.left = rc.left; + locked.top = rc.top; + locked.right = rc.right; + 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 - + (rect.top - surface->header.rect.top) * surface->info.bmiHeader.biWidth - + (rect.left - surface->header.rect.left); - dst = (DWORD *)buffer.bits + rect.top * buffer.stride + rect.left; - width = min( rect.right - rect.left, buffer.stride ); + 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; + width = min( locked.right - locked.left, buffer.stride );
- for (y = rect.top; y < min( buffer.height, rect.bottom); y++) + for (y = locked.top; y < min( buffer.height, locked.bottom ); y++) { if (surface->info.bmiHeader.biCompression == BI_RGB) memcpy( dst, src, width * sizeof(*dst) ); @@ -754,7 +729,7 @@ static void android_surface_flush( struct window_surface *window_surface ) if (rgn_rect) { while (rgn_rect < end && rgn_rect->bottom <= y) rgn_rect++; - apply_line_region( dst, width, rect.left, y, rgn_rect, end ); + apply_line_region( dst, width, locked.left, y, rgn_rect, end ); }
src += surface->info.bmiHeader.biWidth; @@ -765,7 +740,7 @@ static void android_surface_flush( struct window_surface *window_surface ) else TRACE( "Unable to lock surface %p window %p buffer %p\n", surface, surface->hwnd, surface->window );
- window_surface_unlock( window_surface ); + return TRUE; }
/*********************************************************************** @@ -1576,7 +1551,7 @@ BOOL ANDROID_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info }
window_surface_unlock( surface ); - surface->funcs->flush( surface ); + window_surface_flush( surface );
done: window_surface_release( surface ); @@ -1608,7 +1583,7 @@ LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) window_surface_lock( surface ); surface->bounds = surface->rect; window_surface_unlock( surface ); - if (is_argb_surface( surface )) surface->funcs->flush( surface ); + if (is_argb_surface( surface )) window_surface_flush( surface ); } release_win_data( data ); } diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 3edbe783b10..7e296f33a62 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -112,21 +112,11 @@ static void macdrv_surface_set_region(struct window_surface *window_surface, HRG /*********************************************************************** * macdrv_surface_flush */ -static void macdrv_surface_flush(struct window_surface *window_surface) +static BOOL macdrv_surface_flush(struct window_surface *window_surface, const RECT *rect, const RECT *dirty) { struct macdrv_window_surface *surface = get_mac_surface(window_surface); - RECT rect = window_surface->rect; - OffsetRect(&rect, -rect.left, -rect.top); - - window_surface_lock(window_surface); - - TRACE("flushing %p %s bounds %s bits %p\n", surface, wine_dbgstr_rect(&surface->header.rect), - wine_dbgstr_rect(&window_surface->bounds), surface->bits); - - if (intersect_rect(&rect, &rect, &window_surface->bounds)) - macdrv_window_needs_display(surface->window, cgrect_from_rect(rect)); - - window_surface_unlock(window_surface); + macdrv_window_needs_display(surface->window, cgrect_from_rect(*dirty)); + return FALSE; /* bounds are reset asynchronously, from macdrv_get_surface_display_image */ }
/*********************************************************************** diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index f498914588a..04eb6d00860 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1985,7 +1985,7 @@ BOOL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, memcpy(dst_bits, src_bits, bmi->bmiHeader.biSizeImage); add_bounds_rect(&surface->bounds, &rect); window_surface_unlock(surface); - surface->funcs->flush(surface); + window_surface_flush(surface); }
/* The ULW flags are a superset of the LWA flags. */ diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 690038fdbec..3706b6afb97 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -756,7 +756,7 @@ void wayland_window_flush(HWND hwnd) if (!data) return;
if (data->window_surface) - data->window_surface->funcs->flush(data->window_surface); + window_surface_flush(data->window_surface);
wayland_win_data_release(data); } diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index adcbf593984..37fe9b3eb4c 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -341,19 +341,14 @@ static void wayland_shm_buffer_copy(struct wayland_shm_buffer *src, /*********************************************************************** * wayland_window_surface_flush */ -static void wayland_window_surface_flush(struct window_surface *window_surface) +static BOOL wayland_window_surface_flush(struct window_surface *window_surface, const RECT *rect, const RECT *dirty) { struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface); struct wayland_shm_buffer *shm_buffer = NULL; BOOL flushed = FALSE; - RECT damage_rect; HRGN surface_damage_region = NULL; HRGN copy_from_window_region;
- window_surface_lock(window_surface); - - if (!intersect_rect(&damage_rect, &wws->header.rect, &window_surface->bounds)) goto done; - if (!wws->wayland_surface || !wws->wayland_buffer_queue) { ERR("missing wayland surface=%p or buffer_queue=%p, returning\n", @@ -361,11 +356,7 @@ static void wayland_window_surface_flush(struct window_surface *window_surface) goto done; }
- TRACE("surface=%p hwnd=%p surface_rect=%s bounds=%s\n", wws, wws->hwnd, - wine_dbgstr_rect(&wws->header.rect), wine_dbgstr_rect(&window_surface->bounds)); - - surface_damage_region = NtGdiCreateRectRgn(damage_rect.left, damage_rect.top, - damage_rect.right, damage_rect.bottom); + surface_damage_region = NtGdiCreateRectRgn(dirty->left, dirty->top, dirty->right, dirty->bottom); if (!surface_damage_region) { ERR("failed to create surface damage region\n"); @@ -438,9 +429,8 @@ static void wayland_window_surface_flush(struct window_surface *window_surface) wayland_shm_buffer_ref((wws->wayland_surface->latest_window_buffer = shm_buffer));
done: - if (flushed) reset_bounds(&window_surface->bounds); if (surface_damage_region) NtGdiDeleteObjectApp(surface_damage_region); - window_surface_unlock(window_surface); + return flushed; }
/*********************************************************************** diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index ad262d84496..f0d523b6f9c 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1871,67 +1871,47 @@ static void x11drv_surface_set_region( struct window_surface *window_surface, HR /*********************************************************************** * x11drv_surface_flush */ -static void x11drv_surface_flush( struct window_surface *window_surface ) +static BOOL x11drv_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty ) { struct x11drv_window_surface *surface = get_x11_surface( window_surface ); unsigned char *src = surface->bits; unsigned char *dst = (unsigned char *)surface->image->data; - struct bitblt_coords coords;
- window_surface_lock( window_surface ); - coords.x = 0; - coords.y = 0; - coords.width = surface->header.rect.right - surface->header.rect.left; - coords.height = surface->header.rect.bottom - surface->header.rect.top; - SetRect( &coords.visrect, 0, 0, coords.width, coords.height ); - if (intersect_rect( &coords.visrect, &coords.visrect, &window_surface->bounds )) - { - TRACE( "flushing %p %dx%d bounds %s bits %p\n", surface, coords.width, coords.height, - wine_dbgstr_rect( &window_surface->bounds ), surface->bits ); + if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
- if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface ); + if (src != dst) + { + int map[256], *mapping = get_window_surface_mapping( surface->image->bits_per_pixel, map ); + int width_bytes = surface->image->bytes_per_line;
- if (src != dst) - { - int map[256], *mapping = get_window_surface_mapping( surface->image->bits_per_pixel, map ); - int width_bytes = surface->image->bytes_per_line; - - src += coords.visrect.top * width_bytes; - dst += coords.visrect.top * width_bytes; - copy_image_byteswap( &surface->info, src, dst, width_bytes, width_bytes, - coords.visrect.bottom - coords.visrect.top, - surface->byteswap, mapping, ~0u, surface->alpha_bits ); - } - else if (surface->alpha_bits) - { - int x, y, stride = surface->image->bytes_per_line / sizeof(ULONG); - ULONG *ptr = (ULONG *)dst + coords.visrect.top * stride; + src += dirty->top * width_bytes; + dst += dirty->top * width_bytes; + copy_image_byteswap( &surface->info, src, dst, width_bytes, width_bytes, dirty->bottom - dirty->top, + surface->byteswap, mapping, ~0u, surface->alpha_bits ); + } + else if (surface->alpha_bits) + { + int x, y, stride = surface->image->bytes_per_line / sizeof(ULONG); + ULONG *ptr = (ULONG *)dst + dirty->top * stride;
- for (y = coords.visrect.top; y < coords.visrect.bottom; y++, ptr += stride) - for (x = coords.visrect.left; x < coords.visrect.right; x++) - ptr[x] |= surface->alpha_bits; - } + for (y = dirty->top; y < dirty->bottom; y++, ptr += stride) + for (x = dirty->left; x < dirty->right; x++) + ptr[x] |= surface->alpha_bits; + }
#ifdef HAVE_LIBXXSHM - if (surface->shminfo.shmid != -1) - XShmPutImage( gdi_display, surface->window, surface->gc, surface->image, - coords.visrect.left, coords.visrect.top, - surface->header.rect.left + coords.visrect.left, - surface->header.rect.top + coords.visrect.top, - coords.visrect.right - coords.visrect.left, - coords.visrect.bottom - coords.visrect.top, False ); - else + if (surface->shminfo.shmid != -1) + XShmPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, + dirty->top, rect->left + dirty->left, rect->top + dirty->top, + dirty->right - dirty->left, dirty->bottom - dirty->top, False ); + else #endif - XPutImage( gdi_display, surface->window, surface->gc, surface->image, - coords.visrect.left, coords.visrect.top, - surface->header.rect.left + coords.visrect.left, - surface->header.rect.top + coords.visrect.top, - coords.visrect.right - coords.visrect.left, - coords.visrect.bottom - coords.visrect.top ); - XFlush( gdi_display ); - } - reset_bounds( &window_surface->bounds ); - window_surface_unlock( window_surface ); + XPutImage( gdi_display, surface->window, surface->gc, surface->image, dirty->left, + dirty->top, rect->left + dirty->left, rect->top + dirty->top, + dirty->right - dirty->left, dirty->bottom - dirty->top ); + XFlush( gdi_display ); + + return TRUE; }
/*********************************************************************** diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 2070d942056..3e9e0254c91 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -906,7 +906,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev ) data->whole_rect.top - data->client_rect.top );
if (data->vis.visualid != default_visual.visualid) - data->surface->funcs->flush( data->surface ); + window_surface_flush( data->surface ); } OffsetRect( &rect, data->whole_rect.left - data->client_rect.left, data->whole_rect.top - data->client_rect.top ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 27f4b10011c..823a17e3998 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1236,7 +1236,7 @@ static void map_window( HWND hwnd, DWORD new_style ) XMapWindow( data->display, data->whole_window ); XFlush( data->display ); if (data->surface && data->vis.visualid != default_visual.visualid) - data->surface->funcs->flush( data->surface ); + window_surface_flush( data->surface ); } else set_xembed_flags( data, XEMBED_MAPPED );
@@ -2803,7 +2803,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags,
XFlush( data->display ); /* make sure changes are done before we start painting again */ if (data->surface && data->vis.visualid != default_visual.visualid) - data->surface->funcs->flush( data->surface ); + window_surface_flush( data->surface );
release_win_data( data ); } @@ -3050,7 +3050,7 @@ BOOL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, }
window_surface_unlock( surface ); - surface->funcs->flush( surface ); + window_surface_flush( surface );
done: window_surface_release( surface ); diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index cd3e8c6abdc..2721083c6ad 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -213,7 +213,7 @@ struct window_surface_funcs { void* (*get_info)( struct window_surface *surface, BITMAPINFO *info ); void (*set_region)( struct window_surface *surface, HRGN region ); - void (*flush)( struct window_surface *surface ); + BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty ); void (*destroy)( struct window_surface *surface ); };
@@ -235,6 +235,7 @@ 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 ); W32KAPI void window_surface_unlock( struct window_surface *surface ); +W32KAPI void window_surface_flush( struct window_surface *surface );
/* display manager interface, used to initialize display device registry data */