From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 37 ++++++++++++------------------------ dlls/win32u/message.c | 7 ++++--- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/win32u_private.h | 3 +-- dlls/win32u/window.c | 13 ++----------- include/wine/gdi_driver.h | 2 +- 6 files changed, 21 insertions(+), 42 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index be31b909b3f..10a7206ec6f 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -50,8 +50,12 @@ static struct list dce_list = LIST_INIT(dce_list);
#define DCE_CACHE_SIZE 64
-static struct list window_surfaces = LIST_INIT( window_surfaces ); -static pthread_mutex_t surfaces_lock = PTHREAD_MUTEX_INITIALIZER; +struct list *thread_window_surfaces(void) +{ + struct list *window_surfaces = &get_user_thread_info()->window_surfaces; + if (!window_surfaces->next) list_init( window_surfaces ); + return window_surfaces; +}
/******************************************************************* * Dummy window surface for windows that shouldn't get painted. @@ -547,6 +551,7 @@ struct window_surface *window_surface_create( UINT size, const struct window_sur }
pthread_mutex_init( &surface->mutex, NULL ); + list_add_tail( thread_window_surfaces(), &surface->entry );
TRACE( "created surface %p for hwnd %p rect %s\n", surface, hwnd, wine_dbgstr_rect( &surface->rect ) ); return surface; @@ -562,6 +567,7 @@ void window_surface_release( struct window_surface *surface ) ULONG ret = InterlockedDecrement( &surface->ref ); if (!ret) { + list_remove( &surface->entry ); if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex ); if (surface->clip_region) NtGdiDeleteObjectApp( surface->clip_region ); if (surface->color_bitmap) NtGdiDeleteObjectApp( surface->color_bitmap ); @@ -725,22 +731,6 @@ void window_surface_set_shape( struct window_surface *surface, HRGN shape_region window_surface_flush( surface ); }
-/******************************************************************* - * register_window_surface - * - * Register a window surface in the global list, possibly replacing another one. - */ -void register_window_surface( struct window_surface *old, struct window_surface *new ) -{ - if (old == &dummy_surface) old = NULL; - if (new == &dummy_surface) new = NULL; - if (old == new) return; - pthread_mutex_lock( &surfaces_lock ); - if (old) list_remove( &old->entry ); - if (new) list_add_tail( &window_surfaces, &new->entry ); - pthread_mutex_unlock( &surfaces_lock ); -} - /******************************************************************* * flush_window_surfaces * @@ -749,19 +739,16 @@ void register_window_surface( struct window_surface *old, struct window_surface void flush_window_surfaces( BOOL idle ) { static DWORD last_idle; - DWORD now; + DWORD now = NtGetTickCount(); struct window_surface *surface; + struct list *window_surfaces = thread_window_surfaces();
- pthread_mutex_lock( &surfaces_lock ); - now = NtGetTickCount(); if (idle) last_idle = now; /* if not idle, we only flush if there's evidence that the app never goes idle */ - else if ((int)(now - last_idle) < 50) goto done; + else if ((int)(now - last_idle) < 50) return;
- LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry ) + LIST_FOR_EACH_ENTRY( surface, window_surfaces, struct window_surface, entry ) window_surface_flush( surface ); -done: - pthread_mutex_unlock( &surfaces_lock ); }
/*********************************************************************** diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 5fa5e10479d..84ac1ae69c5 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3156,6 +3156,7 @@ static inline LARGE_INTEGER *get_nt_timeout( LARGE_INTEGER *time, DWORD timeout
static DWORD wait_multiple_objects_flush( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags ) { + BOOL flush = !list_empty( thread_window_surfaces() ); LARGE_INTEGER time, now, *abs; DWORD ret;
@@ -3166,10 +3167,10 @@ static DWORD wait_multiple_objects_flush( DWORD count, const HANDLE *handles, DW
do { - flush_window_surfaces( TRUE ); + if (flush) flush_window_surfaces( TRUE ); now.QuadPart = min( time.QuadPart, now.QuadPart + 333333 /* 30 fps */ ); - ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), &now ); - } while (ret == WAIT_TIMEOUT && now.QuadPart < time.QuadPart); + ret = NtWaitForMultipleObjects( count, handles, !(flags & MWMO_WAITALL), !!(flags & MWMO_ALERTABLE), flush ? &now : abs ); + } while (flush && ret == WAIT_TIMEOUT && now.QuadPart < time.QuadPart);
return ret; } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index f5559c5ca4f..4c6f094eae8 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -103,6 +103,7 @@ struct user_thread_info HANDLE server_queue; /* Handle to server-side queue */ DWORD last_getmsg_time; /* Get/PeekMessage last request time */ LONGLONG last_driver_time; /* Get/PeekMessage driver event time */ + struct list window_surfaces; /* window surfaces for this thread */ WORD hook_call_depth; /* Number of recursively called hook procs */ WORD hook_unicode; /* Is current hook unicode? */ HHOOK hook; /* Current hook */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a79e163d0b9..e8bc1e0c62d 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -44,6 +44,7 @@ extern ULONG_PTR set_icon_param( HICON handle, const struct free_icon_params *pa
/* dce.c */ extern struct window_surface dummy_surface; +extern struct list *thread_window_surfaces(void); extern void create_window_surface( HWND hwnd, BOOL create_layered, const RECT *surface_rect, UINT monitor_dpi, struct window_surface **window_surface ); extern struct window_surface *get_driver_window_surface( struct window_surface *surface, UINT monitor_dpi ); @@ -52,8 +53,6 @@ extern void flush_window_surfaces( BOOL idle ); extern void move_window_bits( HWND hwnd, const struct window_rects *rects, const RECT *valid_rects ); extern void move_window_bits_surface( HWND hwnd, const RECT *window_rect, struct window_surface *old_surface, const RECT *old_visible_rect, const RECT *valid_rects ); -extern void register_window_surface( struct window_surface *old, - struct window_surface *new );
extern void window_surface_lock( struct window_surface *surface ); extern void window_surface_unlock( struct window_surface *surface ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 73d9fe283e0..a8ab2986209 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2197,7 +2197,6 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru if (ret) { TRACE( "win %p surface %p -> %p\n", hwnd, old_surface, new_surface ); - register_window_surface( old_surface, new_surface ); if (old_surface) { if (valid_rects) @@ -5201,11 +5200,7 @@ LRESULT destroy_window( HWND hwnd )
NtUserDestroyMenu( menu ); NtUserDestroyMenu( sys_menu ); - if (surface) - { - register_window_surface( surface, NULL ); - window_surface_release( surface ); - } + if (surface) window_surface_release( surface );
detach_client_surfaces( hwnd ); if (win->opengl_drawable) opengl_drawable_release( win->opengl_drawable ); @@ -5368,11 +5363,7 @@ void destroy_thread_windows(void)
NtUserDestroyMenu( entry->menu ); NtUserDestroyMenu( entry->sys_menu ); - if (entry->surface) - { - register_window_surface( entry->surface, NULL ); - window_surface_release( entry->surface ); - } + if (entry->surface) window_surface_release( entry->surface ); free( entry ); } } diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 432f00e8c62..90c10204859 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -295,7 +295,7 @@ struct window_surface_funcs struct window_surface { const struct window_surface_funcs *funcs; /* driver-specific implementations */ - struct list entry; /* entry in global list managed by user32 */ + struct list entry; /* entry in win32u thread window surfaces */ LONG ref; /* reference count */ HWND hwnd; /* window the surface was created for */ RECT rect; /* constant, no locking needed */