mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-01 19:38:31 +00:00
win32u: Use a helper to flush window surface, factor locking and bounds reset.
This commit is contained in:
parent
b44730a39e
commit
5d0efbcc6e
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -56,12 +56,6 @@ static struct wayland_window_surface *wayland_window_surface_cast(
|
|||
return (struct wayland_window_surface *)window_surface;
|
||||
}
|
||||
|
||||
static inline void reset_bounds(RECT *bounds)
|
||||
{
|
||||
bounds->left = bounds->top = INT_MAX;
|
||||
bounds->right = bounds->bottom = INT_MIN;
|
||||
}
|
||||
|
||||
static void buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
struct wayland_shm_buffer *shm_buffer = data;
|
||||
|
@ -341,19 +335,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 +350,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 +423,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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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 ))
|
||||
if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
|
||||
|
||||
if (src != dst)
|
||||
{
|
||||
TRACE( "flushing %p %dx%d bounds %s bits %p\n", surface, coords.width, coords.height,
|
||||
wine_dbgstr_rect( &window_surface->bounds ), surface->bits );
|
||||
int map[256], *mapping = get_window_surface_mapping( surface->image->bits_per_pixel, map );
|
||||
int width_bytes = surface->image->bytes_per_line;
|
||||
|
||||
if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue